diff --git a/.codeqlmanifest.json b/.codeqlmanifest.json index 9ddb2927a0..ac468d9838 100644 --- a/.codeqlmanifest.json +++ b/.codeqlmanifest.json @@ -1 +1 @@ -{ "provide": [ "codeql_modules/*/.codeqlmanifest.json", "cpp/.codeqlmanifest.json"] } +{ "provide": [ "codeql_modules/*/.codeqlmanifest.json", "cpp/.codeqlmanifest.json", "c/.codeqlmanifest.json"] } diff --git a/.github/actions/install-codeql/action.yml b/.github/actions/install-codeql/action.yml index 48913c93e0..25cbb5e123 100644 --- a/.github/actions/install-codeql/action.yml +++ b/.github/actions/install-codeql/action.yml @@ -90,7 +90,7 @@ runs: if [ "$CODEQL_STDLIB_VERSION" != "latest" ] then - pushd codeql-stdlib + push codeql-stdlib echo "::debug::Switching to revision $CODEQL_STDLIB_VERSION" git checkout $CODEQL_STDLIB_VERSION popd diff --git a/.github/workflows/code-scanning-pack-gen.yml b/.github/workflows/code-scanning-pack-gen.yml index 7047f8fc88..b871acdc8f 100644 --- a/.github/workflows/code-scanning-pack-gen.yml +++ b/.github/workflows/code-scanning-pack-gen.yml @@ -5,6 +5,7 @@ on: branches: - main - "rc/**" + push: branches: - main @@ -69,14 +70,17 @@ jobs: run: | PATH=$PATH:$CODEQL_HOME/codeql pip install -r scripts/requirements.txt - find rule_packages/ -name '*.json' -exec basename {} .json \; | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 python3 scripts/generate_rules/generate_package_files.py -a + find rule_packages/cpp -name '*.json' -exec basename {} .json \; | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 python3 scripts/generate_rules/generate_package_files.py -a cpp + find rule_packages/c -name '*.json' -exec basename {} .json \; | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 python3 scripts/generate_rules/generate_package_files.py -a c echo "Generating help markdown file for cert" $CODEQL_LATEST_HOME/codeql/codeql generate query-help -vvv --format=markdown -o cpp/cert/src/ cpp/cert/src/rules + $CODEQL_LATEST_HOME/codeql/codeql generate query-help -vvv --format=markdown -o c/cert/src/ c/cert/src/rules codeql query compile --search-path cpp --threads 0 cpp + codeql query compile --search-path c --search-path cpp --threads 0 c cd .. - zip -r codeql-coding-standards/code-scanning-cpp-query-pack-anon.zip codeql-coding-standards/cpp/ codeql-coding-standards/.codeqlmanifest.json codeql-coding-standards/supported_codeql_configs.json codeql-coding-standards/scripts/deviations codeql-coding-standards/scripts/reports + zip -r codeql-coding-standards/code-scanning-cpp-query-pack-anon.zip codeql-coding-standards/c/ codeql-coding-standards/cpp/ codeql-coding-standards/.codeqlmanifest.json codeql-coding-standards/supported_codeql_configs.json codeql-coding-standards/scripts/deviations codeql-coding-standards/scripts/reports - name: Upload GHAS Query Pack uses: actions/upload-artifact@v2 @@ -91,10 +95,10 @@ jobs: PATH=$PATH:$CODEQL_HOME/codeql mkdir -p lgtm-cpp-query-pack function copy_queries_for_pack { - for q in $(codeql resolve queries cpp/$1/src/codeql-suites/$1-default.qls) + for q in $(codeql resolve queries $2/$1/src/codeql-suites/$1-default.qls) do copy_from_root_name="${q%.*}" - copy_to_root_name=$(realpath --relative-to "./cpp/$1/src/" "$copy_from_root_name") + copy_to_root_name=$(realpath --relative-to "./$2/$1/src/" "$copy_from_root_name") query_dir=$(dirname "lgtm-cpp-query-pack/$copy_to_root_name") mkdir -p "$query_dir" # Copy each selected ql file, plus the related files (qhelp, qhelp implementation) @@ -103,10 +107,18 @@ jobs: cp "$copy_from_root_name.qhelp" "lgtm-cpp-query-pack/$copy_to_root_name.qhelp" done } - echo "Copying autosar-default queries" - copy_queries_for_pack "autosar" - echo "Copying cert-default queries" - copy_queries_for_pack "cert" + + echo "Copying autosar-default queries (CPP)" + copy_queries_for_pack "autosar" "cpp" + echo "Copying cert-default queries (CPP)" + copy_queries_for_pack "cert" "cpp" + + echo "Copying misra-default queries (C)" + copy_queries_for_pack "misra" "c" + echo "Copying cert-default queries (C)" + copy_queries_for_pack "cert" "c" + + # Now copy all the .qll files lgtm_pack_dir=$(realpath lgtm-cpp-query-pack) for query_pack in autosar cert common @@ -122,6 +134,22 @@ jobs: done popd done + + + for query_pack in misra cert common + do + echo "Copying $query_pack qll files" + pushd c/$query_pack/src + for query_library in $(find . -name \*.qll) + do + qll_dir=$(dirname "$lgtm_pack_dir/$query_library") + echo "Making $qll_dir" + mkdir -p "$qll_dir" + cp "$query_library" "$lgtm_pack_dir/$query_library" + done + popd + done + cd lgtm-cpp-query-pack zip -9 -r ../lgtm-cpp-query-pack-anon.zip * @@ -174,9 +202,19 @@ jobs: echo "Generating help markdown file for $s" $CODEQL_LATEST_HOME/codeql/codeql generate query-help -vvv --format=markdown -o cpp/$s/src/ cpp/$s/src/rules done + + for s in "misra" "cert" + do + echo "Generating help markdown file for $s" + $CODEQL_LATEST_HOME/codeql/codeql generate query-help -vvv --format=markdown -o c/$s/src/ c/$s/src/rules + done + + codeql query compile --search-path cpp --threads 0 cpp + codeql query compile --search-path c --search-path cpp --threads 0 c + cd .. - zip -r codeql-coding-standards/code-scanning-cpp-query-pack.zip codeql-coding-standards/cpp/ codeql-coding-standards/.codeqlmanifest.json codeql-coding-standards/supported_codeql_configs.json codeql-coding-standards/scripts/deviations codeql-coding-standards/scripts/reports + zip -r codeql-coding-standards/code-scanning-cpp-query-pack.zip codeql-coding-standards/c/ codeql-coding-standards/cpp/ codeql-coding-standards/.codeqlmanifest.json codeql-coding-standards/supported_codeql_configs.json codeql-coding-standards/scripts/deviations codeql-coding-standards/scripts/reports - name: Upload GHAS Query Pack uses: actions/upload-artifact@v2 @@ -191,18 +229,25 @@ jobs: PATH=$PATH:$CODEQL_HOME/codeql mkdir -p lgtm-cpp-query-pack function copy_queries_for_pack { - for rule_dir in $(codeql resolve queries cpp/$1/src/codeql-suites/$1-default.qls | xargs -L1 dirname | uniq) + for rule_dir in $(codeql resolve queries $2/$1/src/codeql-suites/$1-default.qls | xargs -L1 dirname | uniq) do - copy_to_root="lgtm-cpp-query-pack/$(realpath --relative-to "./cpp/$1/src/" "$rule_dir")" + copy_to_root="lgtm-cpp-query-pack/$(realpath --relative-to "./$2/$1/src/" "$rule_dir")" mkdir -p "$copy_to_root" # Copy each selected ql file, plus the related files (qhelp, qhelp implementation) - find "$rule_dir" -name '*.ql' -o -name '*.qhelp' -o -name '*.cpp' -o -name '*.png' -exec cp -n {} "$copy_to_root" \; + find "$rule_dir" -name '*.ql' -o -name '*.qhelp' -o -name '*.c' -name '*.cpp' -o -name '*.png' -exec cp -n {} "$copy_to_root" \; done } - echo "Copying autosar-default queries" - copy_queries_for_pack "autosar" - echo "Copying cert-default queries" - copy_queries_for_pack "cert" + echo "Copying autosar-default queries (CPP)" + copy_queries_for_pack "autosar" "cpp" + echo "Copying cert-default queries (CPP)" + copy_queries_for_pack "cert" "cpp" + + echo "Copying misra-default queries (C)" + copy_queries_for_pack "misra" "c" + echo "Copying cert-default queries (C)" + copy_queries_for_pack "cert" "c" + + # Now copy all the .qll files lgtm_pack_dir=$(realpath lgtm-cpp-query-pack) for query_pack in autosar cert common @@ -218,6 +263,21 @@ jobs: done popd done + + for query_pack in misra cert common + do + echo "Copying $query_pack qll files" + pushd c/$query_pack/src + for query_library in $(find . -name \*.qll) + do + qll_dir=$(dirname "$lgtm_pack_dir/$query_library") + echo "Making $qll_dir" + mkdir -p "$qll_dir" + cp "$query_library" "$lgtm_pack_dir/$query_library" + done + popd + done + cd lgtm-cpp-query-pack zip -9 -r ../lgtm-cpp-query-pack.zip * diff --git a/.github/workflows/codeql_unit_tests.yml b/.github/workflows/codeql_unit_tests.yml index b8d1ea8274..605489a0e0 100644 --- a/.github/workflows/codeql_unit_tests.yml +++ b/.github/workflows/codeql_unit_tests.yml @@ -23,11 +23,11 @@ jobs: - name: Export unit test matrix id: export-unit-test-matrix run: | + echo "Merging Result:" + python scripts/create_language_matrix.py echo "::set-output name=matrix::$( - jq --compact-output \ - '.supported_environment | map([.+{os: "ubuntu-20.04-xl", codeql_standard_library_ident : .codeql_standard_library | sub("\/"; "_")}]) | flatten | {include: .}' \ - supported_codeql_configs.json - )" + python scripts/create_language_matrix.py | \ + jq --compact-output 'map([.+{os: "ubuntu-20.04-xl", codeql_standard_library_ident : .codeql_standard_library | sub("\/"; "_")}]) | flatten | {include: .}')" run-test-suites: name: Run unit tests @@ -37,7 +37,7 @@ jobs: strategy: fail-fast: false matrix: ${{ fromJSON(needs.prepare-unit-test-matrix.outputs.matrix) }} - + steps: - name: Checkout repository uses: actions/checkout@v2 @@ -99,8 +99,8 @@ jobs: codeql_home = os.environ['CODEQL_HOME'] codeql_bin = os.path.join(codeql_home, 'codeql', 'codeql') - cpp_root = Path(workspace, 'cpp') - test_roots = list(map(str, cpp_root.glob('*/test'))) + language_root = Path(workspace, '${{ matrix.language }}') + test_roots = list(map(str, language_root.glob('*/test'))) for test_root in test_roots: print(f"Executing tests found (recursively) in the directory '{test_root}'") files_to_close = [] @@ -109,11 +109,11 @@ jobs: num_slices = 8 procs = [] for slice in range(1, num_slices+1): - test_report_path = os.path.join(runner_temp, f"test_report_{runner_os}_{cli_version}_{stdlib_ref_ident}_slice_{slice}_of_{num_slices}.json") + test_report_path = os.path.join(runner_temp, "${{ matrix.language }}", f"test_report_{runner_os}_{cli_version}_{stdlib_ref_ident}_slice_{slice}_of_{num_slices}.json") os.makedirs(os.path.dirname(test_report_path), exist_ok=True) test_report_file = open(test_report_path, 'w') files_to_close.append(test_report_file) - procs.append(subprocess.Popen([codeql_bin, "test", "run", "--failing-exitcode=122", f"--slice={slice}/{num_slices}", "--ram=2048", "--format=json", f'--search-path={cpp_root}', *test_roots], stdout=test_report_file, stderr=subprocess.PIPE)) + procs.append(subprocess.Popen([codeql_bin, "test", "run", "--failing-exitcode=122", f"--slice={slice}/{num_slices}", "--ram=2048", "--format=json", f'--search-path={language_root}', *test_roots], stdout=test_report_file, stderr=subprocess.PIPE)) for p in procs: p.wait() if p.returncode != 0: @@ -135,7 +135,7 @@ jobs: with: name: test-results-${{ runner.os }}-${{ matrix.codeql_cli }}-${{ matrix.codeql_standard_library_ident }} path: | - ${{ runner.temp }}/test_report_${{ runner.os }}_${{ matrix.codeql_cli }}_${{ matrix.codeql_standard_library_ident }}_slice_*.json + ${{ runner.temp }}/${{ matrix.language }}/test_report_${{ runner.os }}_${{ matrix.codeql_cli }}_${{ matrix.codeql_standard_library_ident }}_slice_*.json if-no-files-found: error validate-test-results: diff --git a/.github/workflows/create-compiler-validation-report-x86.yml b/.github/workflows/create-compiler-validation-report-x86.yml deleted file mode 100644 index 1f6f0a892d..0000000000 --- a/.github/workflows/create-compiler-validation-report-x86.yml +++ /dev/null @@ -1,53 +0,0 @@ -name: Create compiler validation report (x86) - -on: - push: - branches: - - main - - "rc/**" - pull_request: - branches: - - "**" - workflow_dispatch: - -jobs: - create-compiler-validation-report: - name: Create compiler validation report (x86) - runs-on: windows-latest-xl - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Fetch CodeQL - shell: pwsh - run: | - gh release download -R github/codeql-action codeql-bundle-20220120 --pattern 'codeql-bundle-win64.tar.gz' - tar -zxf codeql-bundle-win64.tar.gz - env: - GITHUB_TOKEN: ${{ github.token }} - - - name: Install Reporting Drivers - shell: pwsh - run: | - choco install wget - choco install msaccess2010-redist - - name: Set path - shell: pwsh - run: echo "$env:GITHUB_WORKSPACE/codeql" | Out-File -FilePath $env:GITHUB_PATH -Append - - - name: Create validation report - shell: pwsh - run: | - . 'scripts/matrix_testing/CreateMatrixTestReport.ps1' -Configuration Clang -AllRules - - - uses: actions/upload-artifact@v2 - with: - name: MatrixTestReport - path: MatrixTestReport-* - - - uses: actions/upload-artifact@v2 - with: - name: MatrixTestReportSummary - path: MatrixTestReportSummary* diff --git a/.github/workflows/create-draft-release.yml b/.github/workflows/create-draft-release.yml index 09f7afa8ee..ef4ae708b0 100644 --- a/.github/workflows/create-draft-release.yml +++ b/.github/workflows/create-draft-release.yml @@ -5,14 +5,8 @@ on: inputs: release_version_tag: description: | - The tag for the new draft release, e.g. v0.5.1 (exact string, including the v). + The tag for the new draft release, e.g. v0.5.1. required: true - - previous_release_version_tag: - description: | - The tag preceding this release, e.g. v0.5.0 (exact string, including the v). - required: true - codeql_analysis_threads: description: | Number of threads to evaluate queries @@ -52,6 +46,6 @@ jobs: - name: Create draft release run: | - scripts/release/create_draft_release.sh ${GITHUB_REF#refs/heads/} "$RELEASE_VERSION_TAG" "$PREVIOUS_RELEASE_VERSION_TAG" + scripts/release/create_draft_release.sh ${GITHUB_REF#refs/heads/} "$RELEASE_VERSION_TAG" env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/upgrade_codeql_dependencies.yml b/.github/workflows/upgrade_codeql_dependencies.yml index 7040af025e..01f8bcf339 100644 --- a/.github/workflows/upgrade_codeql_dependencies.yml +++ b/.github/workflows/upgrade_codeql_dependencies.yml @@ -42,7 +42,9 @@ jobs: unzip -q codeql-linux64.zip - name: Update CodeQL formatting based on new CLI version - run: find cpp -name '*.ql' -or -name '*.qll' | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 codeql/codeql query format --in-place + run: | + find cpp -name '*.ql' -or -name '*.qll' | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 codeql/codeql query format --in-place + find c -name '*.ql' -or -name '*.qll' | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 codeql/codeql query format --in-place - name: Create Pull Request uses: peter-evans/create-pull-request@v3 diff --git a/.github/workflows/validate-coding-standards.yml b/.github/workflows/validate-coding-standards.yml index f49241c9d9..4e1bb0f95b 100644 --- a/.github/workflows/validate-coding-standards.yml +++ b/.github/workflows/validate-coding-standards.yml @@ -9,6 +9,7 @@ on: branches: - main - 'rc/**' + - 'c-coding-standards' env: XARGS_MAX_PROCS: 4 @@ -24,21 +25,37 @@ jobs: - name: Install generate_package_files.py dependencies run: pip install -r scripts/requirements.txt - - name: Validate Package Descriptions + - name: Validate Package Descriptions (CPP) run: | - python scripts/validate-rule-package.py rule_packages/*.json + python scripts/validate-rule-package.py rule_packages/cpp/*.json - - name: Validate Package Descriptions consistency + - name: Validate Package Descriptions (C) run: | - python scripts/verify_rule_package_consistency.py + python scripts/validate-rule-package.py rule_packages/c/*.json - - name: Validate Package Files + - name: Validate Package Descriptions consistency (CPP) run: | - find rule_packages/ -name \*.json -exec basename {} .json \; | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 python3 scripts/generate_rules/generate_package_files.py + python scripts/verify_rule_package_consistency.py cpp + + - name: Validate Package Descriptions consistency (C) + run: | + python scripts/verify_rule_package_consistency.py c + + - name: Validate Package Files (CPP) + run: | + find rule_packages/cpp -name \*.json -exec basename {} .json \; | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 python3 scripts/generate_rules/generate_package_files.py cpp + git diff + git diff --compact-summary + git diff --quiet + + - name: Validate Package Files (C) + run: | + find rule_packages/c -name \*.json -exec basename {} .json \; | xargs --max-procs "$XARGS_MAX_PROCS" --max-args 1 python3 scripts/generate_rules/generate_package_files.py c git diff git diff --compact-summary git diff --quiet + validate-codeql-format: name: "Validate CodeQL Format" runs-on: ubuntu-latest @@ -54,9 +71,18 @@ jobs: env: GITHUB_TOKEN: ${{ github.token }} - - name: Validate CodeQL Format + - name: Validate CodeQL Format (CPP) run: | find cpp -name \*.ql -or -name \*.qll -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" codeql/codeql query format --in-place + + git diff + git diff --compact-summary + git diff --quiet + + - name: Validate CodeQL Format (C) + run: | + find c -name \*.ql -or -name \*.qll -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" codeql/codeql query format --in-place + git diff git diff --compact-summary git diff --quiet @@ -67,7 +93,7 @@ jobs: strategy: fail-fast: false matrix: - language: ['cpp'] + language: ['cpp', 'c'] steps: - name: Checkout uses: actions/checkout@v2 @@ -122,3 +148,26 @@ jobs: git diff git diff --compact-summary git diff --quiet + + validate-c-test-files: + name: Validate C Test Files + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Install clang-format + run: | + sudo apt-get install --yes --quiet --no-install-recommends clang-format + echo "::debug::$(clang-format -version)" + + - name: Validate C++ Test Files + run: | + if ! test -f .clang-format; then + echo "Cannot find .clang-format in '$PWD'. Exiting..." + fi + + find c/*/test -name \*.c -print0 | xargs -0 --max-procs "$XARGS_MAX_PROCS" clang-format --style=file -i --verbose + git diff + git diff --compact-summary + git diff --quiet diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 2d6049652f..a0790f333d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -46,13 +46,13 @@ "label": "๐Ÿ“ Standards Automation: Generate Rule Description File", "type": "shell", "windows": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}Scripts${pathSeparator}python.exe scripts${pathSeparator}generate_rules${pathSeparator}generate_package_description.py ${input:rule_package_name}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}Scripts${pathSeparator}python.exe scripts${pathSeparator}generate_rules${pathSeparator}generate_package_description.py ${input:language} ${input:rule_package_name}" }, "linux": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_description.py ${input:rule_package_name}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_description.py ${input:language} ${input:rule_package_name}" }, "osx": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_description.py ${input:rule_package_name}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_description.py ${input:language} ${input:rule_package_name}" }, "presentation": { "reveal": "always", @@ -68,13 +68,13 @@ "label": "๐Ÿ“ฆ Standards Automation: Generate Package Files", "type": "shell", "windows": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}Scripts${pathSeparator}python.exe scripts${pathSeparator}generate_rules${pathSeparator}generate_package_files.py ${input:rule_package_name}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}Scripts${pathSeparator}python.exe scripts${pathSeparator}generate_rules${pathSeparator}generate_package_files.py ${input:language} ${input:rule_package_name}" }, "linux": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_files.py ${input:rule_package_name}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_files.py ${input:language} ${input:rule_package_name}" }, "osx": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_files.py ${input:rule_package_name}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}generate_rules${pathSeparator}generate_package_files.py ${input:language} ${input:rule_package_name}" }, "presentation": { "reveal": "always", @@ -90,13 +90,13 @@ "label": "๐Ÿงช Standards Automation: Build Case Test DB", "type": "shell", "windows": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}Scripts${pathSeparator}python.exe scripts${pathSeparator}build_test_database.py ${input:standard} ${input:rule}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}Scripts${pathSeparator}python.exe scripts${pathSeparator}build_test_database.py ${input:language} ${input:standard} ${input:rule}" }, "linux": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}build_test_database.py ${input:standard} ${input:rule}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}build_test_database.py ${input:language} ${input:standard} ${input:rule}" }, "osx": { - "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}build_test_database.py ${input:standard} ${input:rule}" + "command": ".${pathSeparator}scripts${pathSeparator}.venv${pathSeparator}bin${pathSeparator}python3 scripts${pathSeparator}build_test_database.py ${input:language} ${input:standard} ${input:rule}" }, "presentation": { "reveal": "always", @@ -164,6 +164,7 @@ "Exceptions2", "Includes", "Invariants", + "IO", "Iterators", "Literals", "Loops", @@ -209,6 +210,16 @@ "common" ] }, + { + "id": "language", + "description": "Name of language", + "default": "cpp", + "type": "pickString", + "options": [ + "cpp", + "c" + ] + }, { "id": "rule", "description": "Rule in package (e.g., M3-9-1)", diff --git a/c/.codeqlmanifest.json b/c/.codeqlmanifest.json new file mode 100644 index 0000000000..384848fdd1 --- /dev/null +++ b/c/.codeqlmanifest.json @@ -0,0 +1,3 @@ +{ "provide": [ + "*/src/qlpack.yml", + "*/test/qlpack.yml" ] } diff --git a/c/cert/src/codeql-suites/cert-default.qls b/c/cert/src/codeql-suites/cert-default.qls new file mode 100644 index 0000000000..c8652930e9 --- /dev/null +++ b/c/cert/src/codeql-suites/cert-default.qls @@ -0,0 +1,9 @@ +- description: CERT C 2016 (Default) +- qlpack: cert-c-coding-standards +- include: + kind: + - problem + - path-problem +- exclude: + tags contain: + - external/cert/default-disabled \ No newline at end of file diff --git a/c/cert/src/codingstandards/c/cert.qll b/c/cert/src/codingstandards/c/cert.qll new file mode 100644 index 0000000000..9c8599d4ea --- /dev/null +++ b/c/cert/src/codingstandards/c/cert.qll @@ -0,0 +1,4 @@ +import cpp +import cert.Customizations +import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.c.RuleMetadata diff --git a/c/cert/src/codingstandards/c/cert/Customizations.qll b/c/cert/src/codingstandards/c/cert/Customizations.qll new file mode 100644 index 0000000000..e5fae10131 --- /dev/null +++ b/c/cert/src/codingstandards/c/cert/Customizations.qll @@ -0,0 +1,8 @@ +/** + * Contains customizations to the CERT-C++ query rules. + * + * This module is imported by `codingstandards/cpp/cert.qll`, so any customizations defined here + * automatically apply to all CERT queries. + */ + +import cpp diff --git a/c/cert/src/qlpack.yml b/c/cert/src/qlpack.yml new file mode 100644 index 0000000000..6523decd27 --- /dev/null +++ b/c/cert/src/qlpack.yml @@ -0,0 +1,4 @@ +name: cert-c-coding-standards +version: 2.0.0 +suites: codeql-suites +libraryPathDependencies: common-c-coding-standards \ No newline at end of file diff --git a/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings-implementation.qhelp b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings-implementation.qhelp new file mode 100644 index 0000000000..a01fab8d10 --- /dev/null +++ b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings-implementation.qhelp @@ -0,0 +1,8 @@ + + + +

None

+
+
\ No newline at end of file diff --git a/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings-standard.qhelp b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings-standard.qhelp new file mode 100644 index 0000000000..99ace9f40b --- /dev/null +++ b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings-standard.qhelp @@ -0,0 +1,29 @@ + + +
+ +
+ +
+

+ ... +

+ +
+ +
+

+ ... +

+
+ +
+ +
+
\ No newline at end of file diff --git a/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.qhelp b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.qhelp new file mode 100644 index 0000000000..7cd34ab9f2 --- /dev/null +++ b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.qhelp @@ -0,0 +1,21 @@ + + + + +

This query implements the CERT-C rule FIO30-C:

+
+

Exclude user input from format strings

+
+
+ +
+ +
+ +
  • + CERT-C: + FIO30-C: Exclude user input from format strings + . +
  • +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql new file mode 100644 index 0000000000..b9df838b06 --- /dev/null +++ b/c/cert/src/rules/FIO30-C/ExcludeUserInputFromFormatStrings.ql @@ -0,0 +1,22 @@ +/** + * @id c/cert/exclude-user-input-from-format-strings + * @name FIO30-C: Exclude user input from format strings + * @description Never call a formatted I/O function with a format string containing user input. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/cert/id/fio30-c + * correctness + * security + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.rules.nonconstantformat.NonConstantFormat + +class ExcludeUserInputFromFormatStringsQuery extends NonConstantFormatSharedQuery { + ExcludeUserInputFromFormatStringsQuery() { + this = IO1Package::excludeUserInputFromFormatStringsQuery() + } +} diff --git a/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof-implementation.qhelp b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof-implementation.qhelp new file mode 100644 index 0000000000..a01fab8d10 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof-implementation.qhelp @@ -0,0 +1,8 @@ + + + +

    None

    +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof-standard.qhelp b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof-standard.qhelp new file mode 100644 index 0000000000..e822d5cfd4 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof-standard.qhelp @@ -0,0 +1,29 @@ + + +
    + +
    + +
    +

    + ... +

    + +
    + +
    +

    + ... +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.qhelp b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.qhelp new file mode 100644 index 0000000000..5ba4f7c808 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.qhelp @@ -0,0 +1,21 @@ + + + + +

    This query implements the CERT-C rule FIO34-C:

    +
    +

    Distinguish between characters read from a file and EOF or WEOF

    +
    +
    + +
    + +
    + +
  • + CERT-C: + FIO34-C: Distinguish between characters read from a file and EOF or WEOF + . +
  • +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql new file mode 100644 index 0000000000..a55c2dbf29 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql @@ -0,0 +1,23 @@ +/** + * @id c/cert/distinguish-between-char-read-from-a-file-and-eof-or-weof + * @name FIO34-C: Distinguish between characters read from a file and EOF or WEOF + * @description File read should be followed by a check for read errors and end of file. + * @kind problem + * @precision high + * @problem.severity error + * @tags external/cert/id/fio34-c + * correctness + * security + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.ReadErrorsAndEOF + +from InBandErrorReadFunctionCall read +where + not isExcluded(read, IO1Package::distinguishBetweenCharReadFromAFileAndEofOrWeofQuery()) and + missingFeofFerrorChecks(read) and + missingEOFWEOFChecks(read) +select read, "The file read is not checked for errors and end of file." diff --git a/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability-implementation.qhelp b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability-implementation.qhelp new file mode 100644 index 0000000000..a01fab8d10 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability-implementation.qhelp @@ -0,0 +1,8 @@ + + + +

    None

    +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability-standard.qhelp b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability-standard.qhelp new file mode 100644 index 0000000000..e822d5cfd4 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability-standard.qhelp @@ -0,0 +1,29 @@ + + +
    + +
    + +
    +

    + ... +

    + +
    + +
    +

    + ... +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.qhelp b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.qhelp new file mode 100644 index 0000000000..4a648e11b0 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.qhelp @@ -0,0 +1,21 @@ + + + + +

    This query implements the CERT-C rule FIO34-C:

    +
    +

    Distinguish between characters read from a file and EOF or WEOF

    +
    +
    + +
    + +
    + +
  • + CERT-C: + FIO34-C: Distinguish between characters read from a file and EOF or WEOF + . +
  • +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql new file mode 100644 index 0000000000..274514e598 --- /dev/null +++ b/c/cert/src/rules/FIO34-C/EndOfFileCheckPortability.ql @@ -0,0 +1,24 @@ +/** + * @id c/cert/end-of-file-check-portability + * @name FIO34-C: Checks against EOF and WEOF are not portable + * @description Checks against EOF are only portable to platforms where type `char` is less wide + * than type `int`. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/cert/id/fio34-c + * correctness + * security + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.ReadErrorsAndEOF + +from EqualityOperation eq +where + not isExcluded(eq, IO1Package::endOfFileCheckPortabilityQuery()) and + isMacroCheck(eq, _) +select eq, + "This check is only portable to platforms where type `char` is less wide than type `int`." diff --git a/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning-implementation.qhelp b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning-implementation.qhelp new file mode 100644 index 0000000000..a01fab8d10 --- /dev/null +++ b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning-implementation.qhelp @@ -0,0 +1,8 @@ + + + +

    None

    +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning-standard.qhelp b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning-standard.qhelp new file mode 100644 index 0000000000..99ace9f40b --- /dev/null +++ b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning-standard.qhelp @@ -0,0 +1,29 @@ + + +
    + +
    + +
    +

    + ... +

    + +
    + +
    +

    + ... +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.qhelp b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.qhelp new file mode 100644 index 0000000000..7de21baaa1 --- /dev/null +++ b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.qhelp @@ -0,0 +1,21 @@ + + + + +

    This query implements the CERT-C rule FIO39-C:

    +
    +

    Do not alternately input and output from a stream without an intervening flush or positioning call

    +
    +
    + +
    + +
    + +
  • + CERT-C: + FIO39-C: Do not alternately input and output from a stream without an intervening flush or positioning call + . +
  • +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql new file mode 100644 index 0000000000..bb1cef3259 --- /dev/null +++ b/c/cert/src/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.ql @@ -0,0 +1,21 @@ +/** + * @id c/cert/do-not-alternately-io-from-a-stream-without-positioning + * @name FIO39-C: Do not alternately input and output from a stream without an intervening flush or positioning call + * @description + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/cert/id/fio39-c + * correctness + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.rules.iofstreammissingpositioning.IOFstreamMissingPositioning + +class DoNotAlternatelyIOFromAStreamWithoutPositioningQuery extends IOFstreamMissingPositioningSharedQuery { + DoNotAlternatelyIOFromAStreamWithoutPositioningQuery() { + this = IO1Package::doNotAlternatelyIOFromAStreamWithoutPositioningQuery() + } +} diff --git a/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded-implementation.qhelp b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded-implementation.qhelp new file mode 100644 index 0000000000..a01fab8d10 --- /dev/null +++ b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded-implementation.qhelp @@ -0,0 +1,8 @@ + + + +

    None

    +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp new file mode 100644 index 0000000000..e822d5cfd4 --- /dev/null +++ b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp @@ -0,0 +1,29 @@ + + +
    + +
    + +
    +

    + ... +

    + +
    + +
    +

    + ... +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.qhelp b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.qhelp new file mode 100644 index 0000000000..d3b9cfb2f5 --- /dev/null +++ b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.qhelp @@ -0,0 +1,21 @@ + + + + +

    This query implements the CERT-C rule FIO42-C:

    +
    +

    Close files when they are no longer needed

    +
    +
    + +
    + +
    + +
  • + CERT-C: + FIO42-C: Close files when they are no longer needed + . +
  • +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql new file mode 100644 index 0000000000..28f7d6eb58 --- /dev/null +++ b/c/cert/src/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql @@ -0,0 +1,173 @@ +/** + * @id c/cert/close-files-when-they-are-no-longer-needed + * @name FIO42-C: Close files when they are no longer needed + * @description + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/cert/id/fio42-c + * correctness + * security + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import semmle.code.cpp.controlflow.StackVariableReachability +import codingstandards.cpp.standardlibrary.FileAccess + +/** + * Extend the NullValue class used by Nullness.qll to include simple -1 as a 'null' value + * (for example 'open' returns -1 if there was an error) + */ +class MinusOne extends NullValue { + MinusOne() { this.(UnaryMinusExpr).getOperand().(Literal).getValue() = "1" } +} + +/** + * 'call' is either a direct call to f, or a possible call to f + * via a function pointer. + */ +predicate mayCallFunction(Expr call, Function f) { + call.(FunctionCall).getTarget() = f or + call.(VariableCall).getVariable().getAnAssignedValue().getAChild*().(FunctionAccess).getTarget() = + f +} + +predicate fopenCallOrIndirect(Expr e) { + // direct fopen call + opened(e) and + // We are only interested in fopen calls that are + // actually closed somehow, as FileNeverClosed + // will catch those that aren't. + fopenCallMayBeClosed(e) + or + exists(ReturnStmt rtn | + // indirect fopen call + mayCallFunction(e, rtn.getEnclosingFunction()) and + ( + // return fopen + fopenCallOrIndirect(rtn.getExpr()) + or + // return variable assigned with fopen + exists(Variable v | + v = rtn.getExpr().(VariableAccess).getTarget() and + fopenCallOrIndirect(v.getAnAssignedValue()) and + not assignedToFieldOrGlobal(v, _) + ) + ) + ) +} + +predicate fcloseCallOrIndirect(FunctionCall fc, Variable v) { + // direct fclose call + fcloseCall(fc, v.getAnAccess()) + or + // indirect fclose call + exists(FunctionCall midcall, Function mid, int arg | + fc.getArgument(arg) = v.getAnAccess() and + mayCallFunction(fc, mid) and + midcall.getEnclosingFunction() = mid and + fcloseCallOrIndirect(midcall, mid.getParameter(arg)) + ) +} + +predicate fopenDefinition(StackVariable v, ControlFlowNode def) { + exists(Expr expr | exprDefinition(v, def, expr) and fopenCallOrIndirect(expr)) +} + +class FOpenVariableReachability extends StackVariableReachabilityWithReassignment { + FOpenVariableReachability() { this = "FOpenVariableReachability" } + + override predicate isSourceActual(ControlFlowNode node, StackVariable v) { + fopenDefinition(v, node) + } + + override predicate isSinkActual(ControlFlowNode node, StackVariable v) { + // node may be used in fopenReaches + exists(node.(AnalysedExpr).getNullSuccessor(v)) or + fcloseCallOrIndirect(node, v) or + assignedToFieldOrGlobal(v, node) or + // node may be used directly in query + v.getFunction() = node.(ReturnStmt).getEnclosingFunction() + } + + override predicate isBarrier(ControlFlowNode node, StackVariable v) { definitionBarrier(v, node) } +} + +/** + * The value from fopen at `def` is still held in Variable `v` upon entering `node`. + */ +predicate fopenVariableReaches(StackVariable v, ControlFlowNode def, ControlFlowNode node) { + exists(FOpenVariableReachability r | + // reachability + r.reachesTo(def, _, node, v) + or + // accept def node itself + r.isSource(def, v) and + node = def + ) +} + +class FOpenReachability extends StackVariableReachabilityExt { + FOpenReachability() { this = "FOpenReachability" } + + override predicate isSource(ControlFlowNode node, StackVariable v) { fopenDefinition(v, node) } + + override predicate isSink(ControlFlowNode node, StackVariable v) { + v.getFunction() = node.(ReturnStmt).getEnclosingFunction() + } + + override predicate isBarrier( + ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, StackVariable v + ) { + isSource(source, v) and + next = node.getASuccessor() and + // the file (stored in any variable `v0`) opened at `source` is closed or + // assigned to a global at node, or NULL checked on the edge node -> next. + exists(StackVariable v0 | fopenVariableReaches(v0, source, node) | + node.(AnalysedExpr).getNullSuccessor(v0) = next or + fcloseCallOrIndirect(node, v0) or + assignedToFieldOrGlobal(v0, node) + ) + } +} + +/** + * The value returned by fopen `def` has not been closed, confirmed to be null, + * or potentially leaked globally upon reaching `node` (regardless of what variable + * it's still held in, if any). + */ +predicate fopenReaches(ControlFlowNode def, ControlFlowNode node) { + exists(FOpenReachability r | r.reaches(def, _, node)) +} + +predicate assignedToFieldOrGlobal(StackVariable v, Expr e) { + // assigned to anything except a StackVariable + // (typically a field or global, but for example also *ptr = v) + e.(Assignment).getRValue() = v.getAnAccess() and + not e.(Assignment).getLValue().(VariableAccess).getTarget() instanceof StackVariable + or + exists(Expr midExpr, Function mid, int arg | + // indirect assignment + e.(FunctionCall).getArgument(arg) = v.getAnAccess() and + mayCallFunction(e, mid) and + midExpr.getEnclosingFunction() = mid and + assignedToFieldOrGlobal(mid.getParameter(arg), midExpr) + ) + or + // assigned to a field via constructor field initializer + e.(ConstructorFieldInit).getExpr() = v.getAnAccess() +} + +from ControlFlowNode def, Stmt ret +where + not isExcluded(def, IO1Package::closeFilesWhenTheyAreNoLongerNeededQuery()) and + fopenReaches(def, ret) and + not exists(StackVariable v | + fopenVariableReaches(v, def, ret) and + ret.getAChild*() = v.getAnAccess() + ) + or + opened(def) and not fopenCallMayBeClosed(def) and ret = def.getControlFlowScope().getEntryPoint() +select def, "The file opened here may not be closed at $@.", ret, "this location" diff --git a/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile-implementation.qhelp b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile-implementation.qhelp new file mode 100644 index 0000000000..a01fab8d10 --- /dev/null +++ b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile-implementation.qhelp @@ -0,0 +1,8 @@ + + + +

    None

    +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile-standard.qhelp b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile-standard.qhelp new file mode 100644 index 0000000000..e822d5cfd4 --- /dev/null +++ b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile-standard.qhelp @@ -0,0 +1,29 @@ + + +
    + +
    + +
    +

    + ... +

    + +
    + +
    +

    + ... +

    +
    + +
    + +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.qhelp b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.qhelp new file mode 100644 index 0000000000..f36147e9bf --- /dev/null +++ b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.qhelp @@ -0,0 +1,21 @@ + + + + +

    This query implements the CERT-C rule FIO46-C:

    +
    +

    Do not access a closed file

    +
    +
    + +
    + +
    + +
  • + CERT-C: + FIO46-C: Do not access a closed file + . +
  • +
    +
    \ No newline at end of file diff --git a/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql new file mode 100644 index 0000000000..81ae3a229a --- /dev/null +++ b/c/cert/src/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.ql @@ -0,0 +1,21 @@ +/** + * @id c/cert/undefined-behavior-accessing-a-closed-file + * @name FIO46-C: Do not access a closed file + * @description Do not access a closed file + * @kind problem + * @precision high + * @problem.severity error + * @tags external/cert/id/fio46-c + * correctness + * external/cert/obligation/rule + */ + +import cpp +import codingstandards.c.cert +import codingstandards.cpp.rules.donotaccessaclosedfile.DoNotAccessAClosedFile + +class UndefinedBehaviorAccessingAClosedFileQuery extends DoNotAccessAClosedFileSharedQuery { + UndefinedBehaviorAccessingAClosedFileQuery() { + this = IO1Package::undefinedBehaviorAccessingAClosedFileQuery() + } +} diff --git a/c/cert/test/qlpack.yml b/c/cert/test/qlpack.yml new file mode 100644 index 0000000000..ff93297bfd --- /dev/null +++ b/c/cert/test/qlpack.yml @@ -0,0 +1,4 @@ +name: cert-c-coding-standards-tests +version: 2.0.0 +libraryPathDependencies: cert-c-coding-standards +extractor: cpp \ No newline at end of file diff --git a/c/cert/test/rules/FIO30-C/ExcludeUserInputFromFormatStrings.testref b/c/cert/test/rules/FIO30-C/ExcludeUserInputFromFormatStrings.testref new file mode 100644 index 0000000000..44520f0d8e --- /dev/null +++ b/c/cert/test/rules/FIO30-C/ExcludeUserInputFromFormatStrings.testref @@ -0,0 +1 @@ +c/common/test/rules/nonconstantformat/NonConstantFormat.ql \ No newline at end of file diff --git a/c/cert/test/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.expected b/c/cert/test/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.expected new file mode 100644 index 0000000000..c2857bb5f0 --- /dev/null +++ b/c/cert/test/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.expected @@ -0,0 +1,9 @@ +| test.c:27:9:27:15 | call to getchar | The file read is not checked for errors and end of file. | +| test.c:35:9:35:15 | call to getchar | The file read is not checked for errors and end of file. | +| test.c:43:9:43:15 | call to getchar | The file read is not checked for errors and end of file. | +| test.c:63:16:63:20 | call to getwc | The file read is not checked for errors and end of file. | +| test.c:107:15:107:21 | call to getchar | The file read is not checked for errors and end of file. | +| test.c:114:9:114:15 | call to getchar | The file read is not checked for errors and end of file. | +| test.c:130:9:130:15 | call to getchar | The file read is not checked for errors and end of file. | +| test.c:146:7:146:10 | call to getc | The file read is not checked for errors and end of file. | +| test.c:148:8:148:11 | call to getc | The file read is not checked for errors and end of file. | diff --git a/c/cert/test/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.qlref b/c/cert/test/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.qlref new file mode 100644 index 0000000000..e4ac52e3ed --- /dev/null +++ b/c/cert/test/rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.qlref @@ -0,0 +1 @@ +rules/FIO34-C/DistinguishBetweenCharReadFromAFileAndEofOrWeof.ql \ No newline at end of file diff --git a/c/cert/test/rules/FIO34-C/EndOfFileCheckPortability.expected b/c/cert/test/rules/FIO34-C/EndOfFileCheckPortability.expected new file mode 100644 index 0000000000..fa49b52d30 --- /dev/null +++ b/c/cert/test/rules/FIO34-C/EndOfFileCheckPortability.expected @@ -0,0 +1,12 @@ +| test.c:11:12:11:19 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:19:12:19:19 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:77:13:77:22 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:96:12:96:19 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:101:10:102:15 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:116:12:116:19 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:120:9:120:16 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:122:12:122:19 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:132:7:132:14 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:137:10:137:25 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:149:7:149:14 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | +| test.c:151:7:151:14 | ... != ... | This check is only portable to platforms where type `char` is less wide than type `int`. | diff --git a/c/cert/test/rules/FIO34-C/EndOfFileCheckPortability.qlref b/c/cert/test/rules/FIO34-C/EndOfFileCheckPortability.qlref new file mode 100644 index 0000000000..f6e69d5f8b --- /dev/null +++ b/c/cert/test/rules/FIO34-C/EndOfFileCheckPortability.qlref @@ -0,0 +1 @@ +rules/FIO34-C/EndOfFileCheckPortability.ql \ No newline at end of file diff --git a/c/cert/test/rules/FIO34-C/test.c b/c/cert/test/rules/FIO34-C/test.c new file mode 100644 index 0000000000..293529dfc1 --- /dev/null +++ b/c/cert/test/rules/FIO34-C/test.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include + +void f1(void) { + int c; + + do { + c = getchar(); // COMPLIANT + } while (c != EOF); // NON_PORTABLE +} + +void f2a(void) { + int c; + + do { + c = getchar(); // COMPLIANT + } while (c != EOF // NON_PORTABLE + || (!feof(stdin) && !ferror(stdin))); +} + +void f2b(void) { + int c; + + do { + c = getchar(); // NON_COMPLIANT + } while (!feof(stdin)); +} + +void f2c(void) { + int c; + + do { + c = getchar(); // NON_COMPLIANT + } while (!ferror(stdin)); +} + +void f2d(void) { + int c; + + do { + c = getchar(); // NON_COMPLIANT + // wrong file: read from `stdin` but checking `stdout` + } while ((!feof(stdout) && !ferror(stdout))); +} + +void f2e(void) { + int c; + + do { + c = getchar(); // COMPLIANT + } while ((!feof(stdin) && !ferror(stdin))); +} + +enum { BUFFER_SIZE = 32 }; + +void f3(void) { + wchar_t buf[BUFFER_SIZE]; + wchar_t wc; + size_t i = 0; + + while ((wc = getwc(stdin)) != L'\n' && wc != WEOF) { // NON_COMPLIANT + if (i < (BUFFER_SIZE - 1)) { + buf[i++] = wc; + } + } + buf[i] = L'\0'; +} + +void f4(void) { + wchar_t buf[BUFFER_SIZE]; + wint_t wc; + size_t i = 0; + + while ((wc = getwc(stdin)) != L'\n' // COMPLIANT + && wc != WEOF) { // NON_PORTABLE + if (i < BUFFER_SIZE - 1) { + buf[i++] = wc; + } + } + + if (feof(stdin) || ferror(stdin)) { + buf[i] = L'\0'; + } else { + /* Received a wide character that resembles WEOF; handle error */ + } +} + +void f5(void) { + int c; + FILE *f = fopen("myfile", "r"); + + do { + c = getc(f); // COMPLIANT + } while (c != EOF); // NON_PORTABLE +} + +void f6a(void) { + int c; + while ((c = getchar()) // COMPLIANT // NON_PORTABLE + != EOF) + ; +} +void f6b(void) { + char c; + while ((c = getchar()) != EOF) // NON_COMPLIANT + ; +} + +void f7(void) { + int c; + do { + c = getchar(); // NON_COMPLIANT + c = getchar(); // COMPLIANT + } while (c != EOF); // NON_PORTABLE + + do { + c = getchar(); // COMPLIANT + if (c != EOF) // NON_PORTABLE + c = getchar(); // COMPLIANT + } while (c != EOF); // NON_PORTABLE +} + +// each call to getchar should be verified againt EOF +void f8(void) { + int c; + int i; + for (i = 3; i > 0; i--) { + c = getchar(); // NON_COMPLIANT + } + if (c != EOF) // NON_PORTABLE + ; +} + +void f9(void) { + while (getchar() != EOF) // NON_PORTABLE + ; // COMPLIANT + + int c; + int c2; + FILE *f = fopen("myfilef", "r"); + int d; + FILE *g = fopen("myfileg", "r"); + + c = getc(f); // NON_COMPLIANT + d = getc(g); // COMPLIANT + c2 = getc(f); // NON_COMPLIANT + if (c != EOF) // NON_PORTABLE + ; + if (d != EOF) // NON_PORTABLE + ; +} \ No newline at end of file diff --git a/c/cert/test/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.testref b/c/cert/test/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.testref new file mode 100644 index 0000000000..4ef72b2eb0 --- /dev/null +++ b/c/cert/test/rules/FIO39-C/DoNotAlternatelyIOFromAStreamWithoutPositioning.testref @@ -0,0 +1 @@ +c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.ql \ No newline at end of file diff --git a/c/cert/test/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.expected b/c/cert/test/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.expected new file mode 100644 index 0000000000..d9b0851f1a --- /dev/null +++ b/c/cert/test/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.expected @@ -0,0 +1,8 @@ +| test.c:7:13:7:17 | call to fopen | The file opened here may not be closed at $@. | test.c:6:31:13:1 | { ... } | this location | +| test.c:16:13:16:19 | call to freopen | The file opened here may not be closed at $@. | test.c:15:31:22:1 | { ... } | this location | +| test.c:25:13:25:19 | call to freopen | The file opened here may not be closed at $@. | test.c:24:32:31:1 | { ... } | this location | +| test.c:46:13:46:17 | call to fopen | The file opened here may not be closed at $@. | test.c:56:3:56:11 | return ... | this location | +| test.c:85:13:85:17 | call to fopen | The file opened here may not be closed at $@. | test.c:89:3:89:27 | return ... | this location | +| test.c:93:13:93:19 | call to freopen | The file opened here may not be closed at $@. | test.c:92:33:104:1 | { ... } | this location | +| test.c:107:13:107:17 | call to fopen | The file opened here may not be closed at $@. | test.c:106:30:113:1 | { ... } | this location | +| test.c:128:12:128:15 | call to open | The file opened here may not be closed at $@. | test.c:127:30:134:1 | { ... } | this location | diff --git a/c/cert/test/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.qlref b/c/cert/test/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.qlref new file mode 100644 index 0000000000..53d28c862c --- /dev/null +++ b/c/cert/test/rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.qlref @@ -0,0 +1 @@ +rules/FIO42-C/CloseFilesWhenTheyAreNoLongerNeeded.ql \ No newline at end of file diff --git a/c/cert/test/rules/FIO42-C/test.c b/c/cert/test/rules/FIO42-C/test.c new file mode 100644 index 0000000000..daa67792f7 --- /dev/null +++ b/c/cert/test/rules/FIO42-C/test.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include + +int f1a(const char *filename) { + FILE *f = fopen(filename, "r"); // NON_COMPLIANT + if (NULL == f) { + return -1; + } + /* ... */ + return 0; +} + +int f1b(const char *filename) { + FILE *f = freopen(filename, "w+", stdout); // NON_COMPLIANT + if (NULL == f) { + return -1; + } + /* ... */ + return 0; +} + +void f1c(const char *filename) { + FILE *f = freopen(filename, "w+", stdout); // NON_COMPLIANT + if (NULL == f) { + return; + } + /* ... */ + // FILE* out of scope not closed +} + +int f2a(const char *filename) { + FILE *f = fopen(filename, "r"); // COMPLIANT + if (NULL == f) { + return -1; + } + /* ... */ + if (fclose(f) == EOF) { + return -1; + } + return 0; +} + +int f2b(const char *filename) { + FILE *f = fopen(filename, "r"); // NON_COMPLIANT + if (NULL == f) { + return -1; + } + if (filename) { + if (fclose(f) == EOF) { + return -1; + } + } + // file not closed on this path + return 0; +} + +// scope prolonged +int f2c(const char *filename) { + FILE *g; + { + FILE *f = fopen(filename, "r"); // COMPLIANT + if (NULL == f) { + return -1; + } + /* ... */ + g = f; + // f out of scope + } + if (fclose(g) == EOF) { + return -1; + } + return 0; +} + +// interprocedural +int closing_helper(FILE *g) { + if (fclose(g) == EOF) { + return -1; + } + return 0; +} +int f2inter(const char *filename) { + FILE *f = fopen(filename, "r"); // COMPLIANT (FALSE_POSITIVE) + if (NULL == f) { + return -1; + } + return closing_helper(f); +} + +int f2cfg(const char *filename) { + FILE *f = freopen(filename, "r", stdout); // NON_COMPLIANT + if (NULL == f) { + return -1; + } + if (filename) { + if (fclose(f) == EOF) { + return -1; + } + } + // file not closed on one path + return 0; +} + +int f3(const char *filename) { + FILE *f = fopen(filename, "w"); // NON_COMPLIANT + if (NULL == f) { + exit(EXIT_FAILURE); + } + /* ... */ + exit(EXIT_SUCCESS); +} + +int f4(const char *filename) { + FILE *f = fopen(filename, "w"); // COMPLIANT + if (NULL == f) { + /* Handle error */ + } + /* ... */ + if (fclose(f) == EOF) { + /* Handle error */ + } + exit(EXIT_SUCCESS); +} + +int f5(const char *filename) { + int fd = open(filename, O_RDONLY, S_IRUSR); // NON_COMPLIANT + if (-1 == fd) { + return -1; + } + /* ... */ + return 0; +} + +int f6(const char *filename) { + int fd = open(filename, O_RDONLY, S_IRUSR); // COMPLIANT + if (-1 == fd) { + return -1; + } + /* ... */ + if (-1 == close(fd)) { + return -1; + } + return 0; +} diff --git a/c/cert/test/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.testref b/c/cert/test/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.testref new file mode 100644 index 0000000000..02420f16e4 --- /dev/null +++ b/c/cert/test/rules/FIO46-C/UndefinedBehaviorAccessingAClosedFile.testref @@ -0,0 +1 @@ +c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.ql \ No newline at end of file diff --git a/c/common/src/qlpack.yml b/c/common/src/qlpack.yml new file mode 100644 index 0000000000..02210d5b3a --- /dev/null +++ b/c/common/src/qlpack.yml @@ -0,0 +1,3 @@ +name: common-c-coding-standards +version: 2.0.0 +libraryPathDependencies: common-cpp-coding-standards diff --git a/c/common/test/includes/standard-library/aio.h b/c/common/test/includes/standard-library/aio.h new file mode 100644 index 0000000000..453c41b748 --- /dev/null +++ b/c/common/test/includes/standard-library/aio.h @@ -0,0 +1,73 @@ +#ifndef _AIO_H +#define _AIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define __NEED_ssize_t +#define __NEED_off_t + +#include + +struct aiocb { + int aio_fildes, aio_lio_opcode, aio_reqprio; + volatile void *aio_buf; + size_t aio_nbytes; + struct sigevent aio_sigevent; + void *__td; + int __lock[2]; + volatile int __err; + ssize_t __ret; + off_t aio_offset; + void *__next, *__prev; + char __dummy4[32-2*sizeof(void *)]; +}; + +#define AIO_CANCELED 0 +#define AIO_NOTCANCELED 1 +#define AIO_ALLDONE 2 + +#define LIO_READ 0 +#define LIO_WRITE 1 +#define LIO_NOP 2 + +#define LIO_WAIT 0 +#define LIO_NOWAIT 1 + +int aio_read(struct aiocb *); +int aio_write(struct aiocb *); +int aio_error(const struct aiocb *); +ssize_t aio_return(struct aiocb *); +int aio_cancel(int, struct aiocb *); +int aio_suspend(const struct aiocb *const [], int, const struct timespec *); +int aio_fsync(int, struct aiocb *); + +int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sigevent *__restrict); + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define aiocb64 aiocb +#define aio_read64 aio_read +#define aio_write64 aio_write +#define aio_error64 aio_error +#define aio_return64 aio_return +#define aio_cancel64 aio_cancel +#define aio_suspend64 aio_suspend +#define aio_fsync64 aio_fsync +#define lio_listio64 lio_listio +#define off64_t off_t +#endif + +#if _REDIR_TIME64 +__REDIR(aio_suspend, __aio_suspend_time64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/alloca.h b/c/common/test/includes/standard-library/alloca.h new file mode 100644 index 0000000000..b8d183d144 --- /dev/null +++ b/c/common/test/includes/standard-library/alloca.h @@ -0,0 +1,19 @@ +#ifndef _ALLOCA_H +#define _ALLOCA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_size_t +#include + +void *alloca(size_t); + +#define alloca __builtin_alloca + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/ar.h b/c/common/test/includes/standard-library/ar.h new file mode 100644 index 0000000000..eafd51d0e7 --- /dev/null +++ b/c/common/test/includes/standard-library/ar.h @@ -0,0 +1,25 @@ +#ifndef _AR_H +#define _AR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARMAG "!\n" +#define SARMAG 8 +#define ARFMAG "`\n" + +struct ar_hdr { + char ar_name[16]; + char ar_date[12]; + char ar_uid[6], ar_gid[6]; + char ar_mode[8]; + char ar_size[10]; + char ar_fmag[2]; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/arpa/ftp.h b/c/common/test/includes/standard-library/arpa/ftp.h new file mode 100644 index 0000000000..fb0a46f2b8 --- /dev/null +++ b/c/common/test/includes/standard-library/arpa/ftp.h @@ -0,0 +1,35 @@ +#ifndef _ARPA_FTP_H +#define _ARPA_FTP_H +#define PRELIM 1 +#define COMPLETE 2 +#define CONTINUE 3 +#define TRANSIENT 4 +#define ERROR 5 +#define TYPE_A 1 +#define TYPE_E 2 +#define TYPE_I 3 +#define TYPE_L 4 +#define FORM_N 1 +#define FORM_T 2 +#define FORM_C 3 +#define STRU_F 1 +#define STRU_R 2 +#define STRU_P 3 +#define MODE_S 1 +#define MODE_B 2 +#define MODE_C 3 +#define REC_ESC '\377' +#define REC_EOR '\001' +#define REC_EOF '\002' +#define BLK_EOR 0x80 +#define BLK_EOF 0x40 +#define BLK_ERRORS 0x20 +#define BLK_RESTART 0x10 +#define BLK_BYTECOUNT 2 +#ifdef FTP_NAMES +char *modenames[] = {"0", "Stream", "Block", "Compressed" }; +char *strunames[] = {"0", "File", "Record", "Page" }; +char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" }; +char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" }; +#endif +#endif diff --git a/c/common/test/includes/standard-library/arpa/inet.h b/c/common/test/includes/standard-library/arpa/inet.h new file mode 100644 index 0000000000..9d20a15ba4 --- /dev/null +++ b/c/common/test/includes/standard-library/arpa/inet.h @@ -0,0 +1,31 @@ +#ifndef _ARPA_INET_H +#define _ARPA_INET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +uint32_t htonl(uint32_t); +uint16_t htons(uint16_t); +uint32_t ntohl(uint32_t); +uint16_t ntohs(uint16_t); + +in_addr_t inet_addr (const char *); +in_addr_t inet_network (const char *); +char *inet_ntoa (struct in_addr); +int inet_pton (int, const char *__restrict, void *__restrict); +const char *inet_ntop (int, const void *__restrict, char *__restrict, socklen_t); + +int inet_aton (const char *, struct in_addr *); +struct in_addr inet_makeaddr(in_addr_t, in_addr_t); +in_addr_t inet_lnaof(struct in_addr); +in_addr_t inet_netof(struct in_addr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/arpa/nameser.h b/c/common/test/includes/standard-library/arpa/nameser.h new file mode 100644 index 0000000000..581925a433 --- /dev/null +++ b/c/common/test/includes/standard-library/arpa/nameser.h @@ -0,0 +1,455 @@ +#ifndef _ARPA_NAMESER_H +#define _ARPA_NAMESER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define __NAMESER 19991006 +#define NS_PACKETSZ 512 +#define NS_MAXDNAME 1025 +#define NS_MAXMSG 65535 +#define NS_MAXCDNAME 255 +#define NS_MAXLABEL 63 +#define NS_HFIXEDSZ 12 +#define NS_QFIXEDSZ 4 +#define NS_RRFIXEDSZ 10 +#define NS_INT32SZ 4 +#define NS_INT16SZ 2 +#define NS_INT8SZ 1 +#define NS_INADDRSZ 4 +#define NS_IN6ADDRSZ 16 +#define NS_CMPRSFLGS 0xc0 +#define NS_DEFAULTPORT 53 + +typedef enum __ns_sect { + ns_s_qd = 0, + ns_s_zn = 0, + ns_s_an = 1, + ns_s_pr = 1, + ns_s_ns = 2, + ns_s_ud = 2, + ns_s_ar = 3, + ns_s_max = 4 +} ns_sect; + +typedef struct __ns_msg { + const unsigned char *_msg, *_eom; + uint16_t _id, _flags, _counts[ns_s_max]; + const unsigned char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const unsigned char *_msg_ptr; +} ns_msg; + +struct _ns_flagdata { int mask, shift; }; +extern const struct _ns_flagdata _ns_flagdata[]; + +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) +#define ns_msg_getflag(handle, flag) \ + (((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift) + +typedef struct __ns_rr { + char name[NS_MAXDNAME]; + uint16_t type; + uint16_t rr_class; + uint32_t ttl; + uint16_t rdlength; + const unsigned char *rdata; +} ns_rr; + +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +typedef enum __ns_flag { + ns_f_qr, + ns_f_opcode, + ns_f_aa, + ns_f_tc, + ns_f_rd, + ns_f_ra, + ns_f_z, + ns_f_ad, + ns_f_cd, + ns_f_rcode, + ns_f_max +} ns_flag; + +typedef enum __ns_opcode { + ns_o_query = 0, + ns_o_iquery = 1, + ns_o_status = 2, + ns_o_notify = 4, + ns_o_update = 5, + ns_o_max = 6 +} ns_opcode; + +typedef enum __ns_rcode { + ns_r_noerror = 0, + ns_r_formerr = 1, + ns_r_servfail = 2, + ns_r_nxdomain = 3, + ns_r_notimpl = 4, + ns_r_refused = 5, + ns_r_yxdomain = 6, + ns_r_yxrrset = 7, + ns_r_nxrrset = 8, + ns_r_notauth = 9, + ns_r_notzone = 10, + ns_r_max = 11, + ns_r_badvers = 16, + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; +}; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 + +typedef enum __ns_type { + ns_t_invalid = 0, + ns_t_a = 1, + ns_t_ns = 2, + ns_t_md = 3, + ns_t_mf = 4, + ns_t_cname = 5, + ns_t_soa = 6, + ns_t_mb = 7, + ns_t_mg = 8, + ns_t_mr = 9, + ns_t_null = 10, + ns_t_wks = 11, + ns_t_ptr = 12, + ns_t_hinfo = 13, + ns_t_minfo = 14, + ns_t_mx = 15, + ns_t_txt = 16, + ns_t_rp = 17, + ns_t_afsdb = 18, + ns_t_x25 = 19, + ns_t_isdn = 20, + ns_t_rt = 21, + ns_t_nsap = 22, + ns_t_nsap_ptr = 23, + ns_t_sig = 24, + ns_t_key = 25, + ns_t_px = 26, + ns_t_gpos = 27, + ns_t_aaaa = 28, + ns_t_loc = 29, + ns_t_nxt = 30, + ns_t_eid = 31, + ns_t_nimloc = 32, + ns_t_srv = 33, + ns_t_atma = 34, + ns_t_naptr = 35, + ns_t_kx = 36, + ns_t_cert = 37, + ns_t_a6 = 38, + ns_t_dname = 39, + ns_t_sink = 40, + ns_t_opt = 41, + ns_t_apl = 42, + ns_t_tkey = 249, + ns_t_tsig = 250, + ns_t_ixfr = 251, + ns_t_axfr = 252, + ns_t_mailb = 253, + ns_t_maila = 254, + ns_t_any = 255, + ns_t_zxfr = 256, + ns_t_max = 65536 +} ns_type; + +#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ + (t) == ns_t_mailb || (t) == ns_t_maila) +#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) +#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) +#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) +#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ + (t) == ns_t_zxfr) + +typedef enum __ns_class { + ns_c_invalid = 0, + ns_c_in = 1, + ns_c_2 = 2, + ns_c_chaos = 3, + ns_c_hs = 4, + ns_c_none = 254, + ns_c_any = 255, + ns_c_max = 65536 +} ns_class; + +typedef enum __ns_key_types { + ns_kt_rsa = 1, + ns_kt_dh = 2, + ns_kt_dsa = 3, + ns_kt_private = 254 +} ns_key_types; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, + cert_t_spki = 2, + cert_t_pgp = 3, + cert_t_url = 253, + cert_t_oid = 254 +} ns_cert_types; + +#define NS_KEY_TYPEMASK 0xC000 +#define NS_KEY_TYPE_AUTH_CONF 0x0000 +#define NS_KEY_TYPE_CONF_ONLY 0x8000 +#define NS_KEY_TYPE_AUTH_ONLY 0x4000 +#define NS_KEY_TYPE_NO_KEY 0xC000 +#define NS_KEY_NO_AUTH 0x8000 +#define NS_KEY_NO_CONF 0x4000 +#define NS_KEY_RESERVED2 0x2000 +#define NS_KEY_EXTENDED_FLAGS 0x1000 +#define NS_KEY_RESERVED4 0x0800 +#define NS_KEY_RESERVED5 0x0400 +#define NS_KEY_NAME_TYPE 0x0300 +#define NS_KEY_NAME_USER 0x0000 +#define NS_KEY_NAME_ENTITY 0x0200 +#define NS_KEY_NAME_ZONE 0x0100 +#define NS_KEY_NAME_RESERVED 0x0300 +#define NS_KEY_RESERVED8 0x0080 +#define NS_KEY_RESERVED9 0x0040 +#define NS_KEY_RESERVED10 0x0020 +#define NS_KEY_RESERVED11 0x0010 +#define NS_KEY_SIGNATORYMASK 0x000F +#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ + NS_KEY_RESERVED4 | \ + NS_KEY_RESERVED5 | \ + NS_KEY_RESERVED8 | \ + NS_KEY_RESERVED9 | \ + NS_KEY_RESERVED10 | \ + NS_KEY_RESERVED11 ) +#define NS_KEY_RESERVED_BITMASK2 0xFFFF +#define NS_ALG_MD5RSA 1 +#define NS_ALG_DH 2 +#define NS_ALG_DSA 3 +#define NS_ALG_DSS NS_ALG_DSA +#define NS_ALG_EXPIRE_ONLY 253 +#define NS_ALG_PRIVATE_OID 254 + +#define NS_KEY_PROT_TLS 1 +#define NS_KEY_PROT_EMAIL 2 +#define NS_KEY_PROT_DNSSEC 3 +#define NS_KEY_PROT_IPSEC 4 +#define NS_KEY_PROT_ANY 255 + +#define NS_MD5RSA_MIN_BITS 512 +#define NS_MD5RSA_MAX_BITS 4096 +#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) +#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) +#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) +#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) + +#define NS_DSA_SIG_SIZE 41 +#define NS_DSA_MIN_SIZE 213 +#define NS_DSA_MAX_BYTES 405 + +#define NS_SIG_TYPE 0 +#define NS_SIG_ALG 2 +#define NS_SIG_LABELS 3 +#define NS_SIG_OTTL 4 +#define NS_SIG_EXPIR 8 +#define NS_SIG_SIGNED 12 +#define NS_SIG_FOOT 16 +#define NS_SIG_SIGNER 18 +#define NS_NXT_BITS 8 +#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_MAX 127 + +#define NS_OPT_DNSSEC_OK 0x8000U +#define NS_OPT_NSID 3 + +#define NS_GET16(s, cp) (void)((s) = ns_get16(((cp)+=2)-2)) +#define NS_GET32(l, cp) (void)((l) = ns_get32(((cp)+=4)-4)) +#define NS_PUT16(s, cp) ns_put16((s), ((cp)+=2)-2) +#define NS_PUT32(l, cp) ns_put32((l), ((cp)+=4)-4) + +unsigned ns_get16(const unsigned char *); +unsigned long ns_get32(const unsigned char *); +void ns_put16(unsigned, unsigned char *); +void ns_put32(unsigned long, unsigned char *); + +int ns_initparse(const unsigned char *, int, ns_msg *); +int ns_parserr(ns_msg *, ns_sect, int, ns_rr *); +int ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int); +int ns_name_uncompress(const unsigned char *, const unsigned char *, const unsigned char *, char *, size_t); + + +#define __BIND 19950621 + +typedef struct { + unsigned id :16; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned qr: 1; + unsigned opcode: 4; + unsigned aa: 1; + unsigned tc: 1; + unsigned rd: 1; + unsigned ra: 1; + unsigned unused :1; + unsigned ad: 1; + unsigned cd: 1; + unsigned rcode :4; +#else + unsigned rd :1; + unsigned tc :1; + unsigned aa :1; + unsigned opcode :4; + unsigned qr :1; + unsigned rcode :4; + unsigned cd: 1; + unsigned ad: 1; + unsigned unused :1; + unsigned ra :1; +#endif + unsigned qdcount :16; + unsigned ancount :16; + unsigned nscount :16; + unsigned arcount :16; +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INT8SZ NS_INT8SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone + +#define DELETE ns_uop_delete +#define ADD ns_uop_add + +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_A6 ns_t_a6 +#define T_DNAME ns_t_dname +#define T_TSIG ns_t_tsig +#define T_IXFR ns_t_ixfr +#define T_AXFR ns_t_axfr +#define T_MAILB ns_t_mailb +#define T_MAILA ns_t_maila +#define T_ANY ns_t_any + +#define C_IN ns_c_in +#define C_CHAOS ns_c_chaos +#define C_HS ns_c_hs +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/arpa/nameser_compat.h b/c/common/test/includes/standard-library/arpa/nameser_compat.h new file mode 100644 index 0000000000..3aac25c98b --- /dev/null +++ b/c/common/test/includes/standard-library/arpa/nameser_compat.h @@ -0,0 +1,2 @@ +#include + diff --git a/c/common/test/includes/standard-library/arpa/telnet.h b/c/common/test/includes/standard-library/arpa/telnet.h new file mode 100644 index 0000000000..e2ad974295 --- /dev/null +++ b/c/common/test/includes/standard-library/arpa/telnet.h @@ -0,0 +1,251 @@ +#ifndef _ARPA_TELNET_H +#define _ARPA_TELNET_H + +#define IAC 255 +#define DONT 254 +#define DO 253 +#define WONT 252 +#define WILL 251 +#define SB 250 +#define GA 249 +#define EL 248 +#define EC 247 +#define AYT 246 +#define AO 245 +#define IP 244 +#define BREAK 243 +#define DM 242 +#define NOP 241 +#define SE 240 +#define EOR 239 +#define ABORT 238 +#define SUSP 237 +#define xEOF 236 + +#define SYNCH 242 + +#define telcmds ((char [][6]){ "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0 }) + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ + (unsigned int)(x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +#define TELOPT_BINARY 0 +#define TELOPT_ECHO 1 +#define TELOPT_RCP 2 +#define TELOPT_SGA 3 +#define TELOPT_NAMS 4 +#define TELOPT_STATUS 5 +#define TELOPT_TM 6 +#define TELOPT_RCTE 7 +#define TELOPT_NAOL 8 +#define TELOPT_NAOP 9 +#define TELOPT_NAOCRD 10 +#define TELOPT_NAOHTS 11 +#define TELOPT_NAOHTD 12 +#define TELOPT_NAOFFD 13 +#define TELOPT_NAOVTS 14 +#define TELOPT_NAOVTD 15 +#define TELOPT_NAOLFD 16 +#define TELOPT_XASCII 17 +#define TELOPT_LOGOUT 18 +#define TELOPT_BM 19 +#define TELOPT_DET 20 +#define TELOPT_SUPDUP 21 +#define TELOPT_SUPDUPOUTPUT 22 +#define TELOPT_SNDLOC 23 +#define TELOPT_TTYPE 24 +#define TELOPT_EOR 25 +#define TELOPT_TUID 26 +#define TELOPT_OUTMRK 27 +#define TELOPT_TTYLOC 28 +#define TELOPT_3270REGIME 29 +#define TELOPT_X3PAD 30 +#define TELOPT_NAWS 31 +#define TELOPT_TSPEED 32 +#define TELOPT_LFLOW 33 +#define TELOPT_LINEMODE 34 +#define TELOPT_XDISPLOC 35 +#define TELOPT_OLD_ENVIRON 36 +#define TELOPT_AUTHENTICATION 37/* Authenticate */ +#define TELOPT_ENCRYPT 38 +#define TELOPT_NEW_ENVIRON 39 +#define TELOPT_EXOPL 255 + + +#define NTELOPTS (1+TELOPT_NEW_ENVIRON) +#ifdef TELOPTS +char *telopts[NTELOPTS+1] = { + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", + "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", + "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", + "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", + "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", + "TACACS UID", "OUTPUT MARKING", "TTYLOC", + "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", + "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", + "ENCRYPT", "NEW-ENVIRON", + 0, +}; +#define TELOPT_FIRST TELOPT_BINARY +#define TELOPT_LAST TELOPT_NEW_ENVIRON +#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) +#define TELOPT(x) telopts[(x)-TELOPT_FIRST] +#endif + +#define TELQUAL_IS 0 +#define TELQUAL_SEND 1 +#define TELQUAL_INFO 2 +#define TELQUAL_REPLY 2 +#define TELQUAL_NAME 3 + +#define LFLOW_OFF 0 +#define LFLOW_ON 1 +#define LFLOW_RESTART_ANY 2 +#define LFLOW_RESTART_XON 3 + + +#define LM_MODE 1 +#define LM_FORWARDMASK 2 +#define LM_SLC 3 + +#define MODE_EDIT 0x01 +#define MODE_TRAPSIG 0x02 +#define MODE_ACK 0x04 +#define MODE_SOFT_TAB 0x08 +#define MODE_LIT_ECHO 0x10 + +#define MODE_MASK 0x1f + +#define MODE_FLOW 0x0100 +#define MODE_ECHO 0x0200 +#define MODE_INBIN 0x0400 +#define MODE_OUTBIN 0x0800 +#define MODE_FORCE 0x1000 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 + +#define NSLC 18 + +#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ + "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ + "LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0, +#ifdef SLC_NAMES +char *slc_names[] = { + SLC_NAMELIST +}; +#else +extern char *slc_names[]; +#define SLC_NAMES SLC_NAMELIST +#endif + +#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) +#define SLC_NAME(x) slc_names[x] + +#define SLC_NOSUPPORT 0 +#define SLC_CANTCHANGE 1 +#define SLC_VARIABLE 2 +#define SLC_DEFAULT 3 +#define SLC_LEVELBITS 0x03 + +#define SLC_FUNC 0 +#define SLC_FLAGS 1 +#define SLC_VALUE 2 + +#define SLC_ACK 0x80 +#define SLC_FLUSHIN 0x40 +#define SLC_FLUSHOUT 0x20 + +#define OLD_ENV_VAR 1 +#define OLD_ENV_VALUE 0 +#define NEW_ENV_VAR 0 +#define NEW_ENV_VALUE 1 +#define ENV_ESC 2 +#define ENV_USERVAR 3 + +#define AUTH_WHO_CLIENT 0 +#define AUTH_WHO_SERVER 1 +#define AUTH_WHO_MASK 1 + +#define AUTH_HOW_ONE_WAY 0 +#define AUTH_HOW_MUTUAL 2 +#define AUTH_HOW_MASK 2 + +#define AUTHTYPE_NULL 0 +#define AUTHTYPE_KERBEROS_V4 1 +#define AUTHTYPE_KERBEROS_V5 2 +#define AUTHTYPE_SPX 3 +#define AUTHTYPE_MINK 4 +#define AUTHTYPE_CNT 5 + +#define AUTHTYPE_TEST 99 + +#ifdef AUTH_NAMES +char *authtype_names[] = { + "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0, +}; +#else +extern char *authtype_names[]; +#endif + +#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) +#define AUTHTYPE_NAME(x) authtype_names[x] + +#define ENCRYPT_IS 0 +#define ENCRYPT_SUPPORT 1 +#define ENCRYPT_REPLY 2 +#define ENCRYPT_START 3 +#define ENCRYPT_END 4 +#define ENCRYPT_REQSTART 5 +#define ENCRYPT_REQEND 6 +#define ENCRYPT_ENC_KEYID 7 +#define ENCRYPT_DEC_KEYID 8 +#define ENCRYPT_CNT 9 + +#define ENCTYPE_ANY 0 +#define ENCTYPE_DES_CFB64 1 +#define ENCTYPE_DES_OFB64 2 +#define ENCTYPE_CNT 3 + +#ifdef ENCRYPT_NAMES +char *encrypt_names[] = { + "IS", "SUPPORT", "REPLY", "START", "END", + "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", + 0, +}; +char *enctype_names[] = { + "ANY", "DES_CFB64", "DES_OFB64", 0, +}; +#else +extern char *encrypt_names[]; +extern char *enctype_names[]; +#endif + + +#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) +#define ENCRYPT_NAME(x) encrypt_names[x] + +#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) +#define ENCTYPE_NAME(x) enctype_names[x] + +#endif diff --git a/c/common/test/includes/standard-library/arpa/tftp.h b/c/common/test/includes/standard-library/arpa/tftp.h new file mode 100644 index 0000000000..799c54f221 --- /dev/null +++ b/c/common/test/includes/standard-library/arpa/tftp.h @@ -0,0 +1,31 @@ +#ifndef _ARPA_TFTP_H +#define _ARPA_TFTP_H +#define SEGSIZE 512 +#define RRQ 01 +#define WRQ 02 +#define DATA 03 +#define ACK 04 +#define ERROR 05 +struct tftphdr { + short th_opcode; + union { + unsigned short tu_block; + short tu_code; + char tu_stuff[1]; + } th_u; + char th_data[1]; +}; +#define th_block th_u.tu_block +#define th_code th_u.tu_code +#define th_stuff th_u.tu_stuff +#define th_msg th_data +#define EUNDEF 0 +#define ENOTFOUND 1 +#define EACCESS 2 +#define ENOSPACE 3 +#define EBADOP 4 +#define EBADID 5 +#define EEXISTS 6 +#define ENOUSER 7 +#endif + diff --git a/c/common/test/includes/standard-library/assert.h b/c/common/test/includes/standard-library/assert.h new file mode 100644 index 0000000000..d14ec94e7a --- /dev/null +++ b/c/common/test/includes/standard-library/assert.h @@ -0,0 +1,23 @@ +#include + +#undef assert + +#ifdef NDEBUG +#define assert(x) (void)0 +#else +#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__, __func__),0))) +#endif + +#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus) +#define static_assert _Static_assert +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_Noreturn void __assert_fail (const char *, const char *, int, const char *); + +#ifdef __cplusplus +} +#endif diff --git a/c/common/test/includes/standard-library/bits/alltypes.h b/c/common/test/includes/standard-library/bits/alltypes.h new file mode 100644 index 0000000000..b5d6f52376 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/alltypes.h @@ -0,0 +1,415 @@ +#define _Addr long +#define _Int64 long +#define _Reg long + +#define __BYTE_ORDER 1234 +#define __LONG_MAX 0x7fffffffffffffffL + +#ifndef __cplusplus +#if defined(__NEED_wchar_t) && !defined(__DEFINED_wchar_t) +typedef int wchar_t; +#define __DEFINED_wchar_t +#endif + +#endif + +#if defined(__FLT_EVAL_METHOD__) && __FLT_EVAL_METHOD__ == 2 +#if defined(__NEED_float_t) && !defined(__DEFINED_float_t) +typedef long double float_t; +#define __DEFINED_float_t +#endif + +#if defined(__NEED_double_t) && !defined(__DEFINED_double_t) +typedef long double double_t; +#define __DEFINED_double_t +#endif + +#else +#if defined(__NEED_float_t) && !defined(__DEFINED_float_t) +typedef float float_t; +#define __DEFINED_float_t +#endif + +#if defined(__NEED_double_t) && !defined(__DEFINED_double_t) +typedef double double_t; +#define __DEFINED_double_t +#endif + +#endif + +#if defined(__NEED_max_align_t) && !defined(__DEFINED_max_align_t) +typedef struct { long long __ll; long double __ld; } max_align_t; +#define __DEFINED_max_align_t +#endif + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __USE_TIME_BITS64 1 + +#if defined(__NEED_size_t) && !defined(__DEFINED_size_t) +typedef unsigned _Addr size_t; +#define __DEFINED_size_t +#endif + +#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t) +typedef unsigned _Addr uintptr_t; +#define __DEFINED_uintptr_t +#endif + +#if defined(__NEED_ptrdiff_t) && !defined(__DEFINED_ptrdiff_t) +typedef _Addr ptrdiff_t; +#define __DEFINED_ptrdiff_t +#endif + +#if defined(__NEED_ssize_t) && !defined(__DEFINED_ssize_t) +typedef _Addr ssize_t; +#define __DEFINED_ssize_t +#endif + +#if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t) +typedef _Addr intptr_t; +#define __DEFINED_intptr_t +#endif + +#if defined(__NEED_regoff_t) && !defined(__DEFINED_regoff_t) +typedef _Addr regoff_t; +#define __DEFINED_regoff_t +#endif + +#if defined(__NEED_register_t) && !defined(__DEFINED_register_t) +typedef _Reg register_t; +#define __DEFINED_register_t +#endif + +#if defined(__NEED_time_t) && !defined(__DEFINED_time_t) +typedef _Int64 time_t; +#define __DEFINED_time_t +#endif + +#if defined(__NEED_suseconds_t) && !defined(__DEFINED_suseconds_t) +typedef _Int64 suseconds_t; +#define __DEFINED_suseconds_t +#endif + + +#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t) +typedef signed char int8_t; +#define __DEFINED_int8_t +#endif + +#if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t) +typedef signed short int16_t; +#define __DEFINED_int16_t +#endif + +#if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t) +typedef signed int int32_t; +#define __DEFINED_int32_t +#endif + +#if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t) +typedef signed _Int64 int64_t; +#define __DEFINED_int64_t +#endif + +#if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t) +typedef signed _Int64 intmax_t; +#define __DEFINED_intmax_t +#endif + +#if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t) +typedef unsigned char uint8_t; +#define __DEFINED_uint8_t +#endif + +#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t) +typedef unsigned short uint16_t; +#define __DEFINED_uint16_t +#endif + +#if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t) +typedef unsigned int uint32_t; +#define __DEFINED_uint32_t +#endif + +#if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t) +typedef unsigned _Int64 uint64_t; +#define __DEFINED_uint64_t +#endif + +#if defined(__NEED_u_int64_t) && !defined(__DEFINED_u_int64_t) +typedef unsigned _Int64 u_int64_t; +#define __DEFINED_u_int64_t +#endif + +#if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t) +typedef unsigned _Int64 uintmax_t; +#define __DEFINED_uintmax_t +#endif + + +#if defined(__NEED_mode_t) && !defined(__DEFINED_mode_t) +typedef unsigned mode_t; +#define __DEFINED_mode_t +#endif + +#if defined(__NEED_nlink_t) && !defined(__DEFINED_nlink_t) +typedef unsigned _Reg nlink_t; +#define __DEFINED_nlink_t +#endif + +#if defined(__NEED_off_t) && !defined(__DEFINED_off_t) +typedef _Int64 off_t; +#define __DEFINED_off_t +#endif + +#if defined(__NEED_ino_t) && !defined(__DEFINED_ino_t) +typedef unsigned _Int64 ino_t; +#define __DEFINED_ino_t +#endif + +#if defined(__NEED_dev_t) && !defined(__DEFINED_dev_t) +typedef unsigned _Int64 dev_t; +#define __DEFINED_dev_t +#endif + +#if defined(__NEED_blksize_t) && !defined(__DEFINED_blksize_t) +typedef long blksize_t; +#define __DEFINED_blksize_t +#endif + +#if defined(__NEED_blkcnt_t) && !defined(__DEFINED_blkcnt_t) +typedef _Int64 blkcnt_t; +#define __DEFINED_blkcnt_t +#endif + +#if defined(__NEED_fsblkcnt_t) && !defined(__DEFINED_fsblkcnt_t) +typedef unsigned _Int64 fsblkcnt_t; +#define __DEFINED_fsblkcnt_t +#endif + +#if defined(__NEED_fsfilcnt_t) && !defined(__DEFINED_fsfilcnt_t) +typedef unsigned _Int64 fsfilcnt_t; +#define __DEFINED_fsfilcnt_t +#endif + + +#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t) +typedef unsigned wint_t; +#define __DEFINED_wint_t +#endif + +#if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t) +typedef unsigned long wctype_t; +#define __DEFINED_wctype_t +#endif + + +#if defined(__NEED_timer_t) && !defined(__DEFINED_timer_t) +typedef void * timer_t; +#define __DEFINED_timer_t +#endif + +#if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t) +typedef int clockid_t; +#define __DEFINED_clockid_t +#endif + +#if defined(__NEED_clock_t) && !defined(__DEFINED_clock_t) +typedef long clock_t; +#define __DEFINED_clock_t +#endif + +#if defined(__NEED_struct_timeval) && !defined(__DEFINED_struct_timeval) +struct timeval { time_t tv_sec; suseconds_t tv_usec; }; +#define __DEFINED_struct_timeval +#endif + +#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec) +struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); }; +#define __DEFINED_struct_timespec +#endif + + +#if defined(__NEED_pid_t) && !defined(__DEFINED_pid_t) +typedef int pid_t; +#define __DEFINED_pid_t +#endif + +#if defined(__NEED_id_t) && !defined(__DEFINED_id_t) +typedef unsigned id_t; +#define __DEFINED_id_t +#endif + +#if defined(__NEED_uid_t) && !defined(__DEFINED_uid_t) +typedef unsigned uid_t; +#define __DEFINED_uid_t +#endif + +#if defined(__NEED_gid_t) && !defined(__DEFINED_gid_t) +typedef unsigned gid_t; +#define __DEFINED_gid_t +#endif + +#if defined(__NEED_key_t) && !defined(__DEFINED_key_t) +typedef int key_t; +#define __DEFINED_key_t +#endif + +#if defined(__NEED_useconds_t) && !defined(__DEFINED_useconds_t) +typedef unsigned useconds_t; +#define __DEFINED_useconds_t +#endif + + +#ifdef __cplusplus +#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) +typedef unsigned long pthread_t; +#define __DEFINED_pthread_t +#endif + +#else +#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) +typedef struct __pthread * pthread_t; +#define __DEFINED_pthread_t +#endif + +#endif +#if defined(__NEED_pthread_once_t) && !defined(__DEFINED_pthread_once_t) +typedef int pthread_once_t; +#define __DEFINED_pthread_once_t +#endif + +#if defined(__NEED_pthread_key_t) && !defined(__DEFINED_pthread_key_t) +typedef unsigned pthread_key_t; +#define __DEFINED_pthread_key_t +#endif + +#if defined(__NEED_pthread_spinlock_t) && !defined(__DEFINED_pthread_spinlock_t) +typedef int pthread_spinlock_t; +#define __DEFINED_pthread_spinlock_t +#endif + +#if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t) +typedef struct { unsigned __attr; } pthread_mutexattr_t; +#define __DEFINED_pthread_mutexattr_t +#endif + +#if defined(__NEED_pthread_condattr_t) && !defined(__DEFINED_pthread_condattr_t) +typedef struct { unsigned __attr; } pthread_condattr_t; +#define __DEFINED_pthread_condattr_t +#endif + +#if defined(__NEED_pthread_barrierattr_t) && !defined(__DEFINED_pthread_barrierattr_t) +typedef struct { unsigned __attr; } pthread_barrierattr_t; +#define __DEFINED_pthread_barrierattr_t +#endif + +#if defined(__NEED_pthread_rwlockattr_t) && !defined(__DEFINED_pthread_rwlockattr_t) +typedef struct { unsigned __attr[2]; } pthread_rwlockattr_t; +#define __DEFINED_pthread_rwlockattr_t +#endif + + +#if defined(__NEED_struct__IO_FILE) && !defined(__DEFINED_struct__IO_FILE) +struct _IO_FILE { char __x; }; +#define __DEFINED_struct__IO_FILE +#endif + +#if defined(__NEED_FILE) && !defined(__DEFINED_FILE) +typedef struct _IO_FILE FILE; +#define __DEFINED_FILE +#endif + + +#if defined(__NEED_va_list) && !defined(__DEFINED_va_list) +typedef __builtin_va_list va_list; +#define __DEFINED_va_list +#endif + +#if defined(__NEED___isoc_va_list) && !defined(__DEFINED___isoc_va_list) +typedef __builtin_va_list __isoc_va_list; +#define __DEFINED___isoc_va_list +#endif + + +#if defined(__NEED_mbstate_t) && !defined(__DEFINED_mbstate_t) +typedef struct __mbstate_t { unsigned __opaque1, __opaque2; } mbstate_t; +#define __DEFINED_mbstate_t +#endif + + +#if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t) +typedef struct __locale_struct * locale_t; +#define __DEFINED_locale_t +#endif + + +#if defined(__NEED_sigset_t) && !defined(__DEFINED_sigset_t) +typedef struct __sigset_t { unsigned long __bits[128/sizeof(long)]; } sigset_t; +#define __DEFINED_sigset_t +#endif + + +#if defined(__NEED_struct_iovec) && !defined(__DEFINED_struct_iovec) +struct iovec { void *iov_base; size_t iov_len; }; +#define __DEFINED_struct_iovec +#endif + + +#if defined(__NEED_struct_winsize) && !defined(__DEFINED_struct_winsize) +struct winsize { unsigned short ws_row, ws_col, ws_xpixel, ws_ypixel; }; +#define __DEFINED_struct_winsize +#endif + + +#if defined(__NEED_socklen_t) && !defined(__DEFINED_socklen_t) +typedef unsigned socklen_t; +#define __DEFINED_socklen_t +#endif + +#if defined(__NEED_sa_family_t) && !defined(__DEFINED_sa_family_t) +typedef unsigned short sa_family_t; +#define __DEFINED_sa_family_t +#endif + + +#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) +typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t; +#define __DEFINED_pthread_attr_t +#endif + +#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t) +typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } pthread_mutex_t; +#define __DEFINED_pthread_mutex_t +#endif + +#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t) +typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t; +#define __DEFINED_mtx_t +#endif + +#if defined(__NEED_pthread_cond_t) && !defined(__DEFINED_pthread_cond_t) +typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } pthread_cond_t; +#define __DEFINED_pthread_cond_t +#endif + +#if defined(__NEED_cnd_t) && !defined(__DEFINED_cnd_t) +typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } cnd_t; +#define __DEFINED_cnd_t +#endif + +#if defined(__NEED_pthread_rwlock_t) && !defined(__DEFINED_pthread_rwlock_t) +typedef struct { union { int __i[sizeof(long)==8?14:8]; volatile int __vi[sizeof(long)==8?14:8]; void *__p[sizeof(long)==8?7:8]; } __u; } pthread_rwlock_t; +#define __DEFINED_pthread_rwlock_t +#endif + +#if defined(__NEED_pthread_barrier_t) && !defined(__DEFINED_pthread_barrier_t) +typedef struct { union { int __i[sizeof(long)==8?8:5]; volatile int __vi[sizeof(long)==8?8:5]; void *__p[sizeof(long)==8?4:5]; } __u; } pthread_barrier_t; +#define __DEFINED_pthread_barrier_t +#endif + + +#undef _Addr +#undef _Int64 +#undef _Reg diff --git a/c/common/test/includes/standard-library/bits/dirent.h b/c/common/test/includes/standard-library/bits/dirent.h new file mode 100644 index 0000000000..c845fe82dd --- /dev/null +++ b/c/common/test/includes/standard-library/bits/dirent.h @@ -0,0 +1,11 @@ +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE + +struct dirent { + ino_t d_ino; + off_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; diff --git a/c/common/test/includes/standard-library/bits/errno.h b/c/common/test/includes/standard-library/bits/errno.h new file mode 100644 index 0000000000..d2e1eeee05 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/errno.h @@ -0,0 +1,134 @@ +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 +#define ELOOP 40 +#define EWOULDBLOCK EAGAIN +#define ENOMSG 42 +#define EIDRM 43 +#define ECHRNG 44 +#define EL2NSYNC 45 +#define EL3HLT 46 +#define EL3RST 47 +#define ELNRNG 48 +#define EUNATCH 49 +#define ENOCSI 50 +#define EL2HLT 51 +#define EBADE 52 +#define EBADR 53 +#define EXFULL 54 +#define ENOANO 55 +#define EBADRQC 56 +#define EBADSLT 57 +#define EDEADLOCK EDEADLK +#define EBFONT 59 +#define ENOSTR 60 +#define ENODATA 61 +#define ETIME 62 +#define ENOSR 63 +#define ENONET 64 +#define ENOPKG 65 +#define EREMOTE 66 +#define ENOLINK 67 +#define EADV 68 +#define ESRMNT 69 +#define ECOMM 70 +#define EPROTO 71 +#define EMULTIHOP 72 +#define EDOTDOT 73 +#define EBADMSG 74 +#define EOVERFLOW 75 +#define ENOTUNIQ 76 +#define EBADFD 77 +#define EREMCHG 78 +#define ELIBACC 79 +#define ELIBBAD 80 +#define ELIBSCN 81 +#define ELIBMAX 82 +#define ELIBEXEC 83 +#define EILSEQ 84 +#define ERESTART 85 +#define ESTRPIPE 86 +#define EUSERS 87 +#define ENOTSOCK 88 +#define EDESTADDRREQ 89 +#define EMSGSIZE 90 +#define EPROTOTYPE 91 +#define ENOPROTOOPT 92 +#define EPROTONOSUPPORT 93 +#define ESOCKTNOSUPPORT 94 +#define EOPNOTSUPP 95 +#define ENOTSUP EOPNOTSUPP +#define EPFNOSUPPORT 96 +#define EAFNOSUPPORT 97 +#define EADDRINUSE 98 +#define EADDRNOTAVAIL 99 +#define ENETDOWN 100 +#define ENETUNREACH 101 +#define ENETRESET 102 +#define ECONNABORTED 103 +#define ECONNRESET 104 +#define ENOBUFS 105 +#define EISCONN 106 +#define ENOTCONN 107 +#define ESHUTDOWN 108 +#define ETOOMANYREFS 109 +#define ETIMEDOUT 110 +#define ECONNREFUSED 111 +#define EHOSTDOWN 112 +#define EHOSTUNREACH 113 +#define EALREADY 114 +#define EINPROGRESS 115 +#define ESTALE 116 +#define EUCLEAN 117 +#define ENOTNAM 118 +#define ENAVAIL 119 +#define EISNAM 120 +#define EREMOTEIO 121 +#define EDQUOT 122 +#define ENOMEDIUM 123 +#define EMEDIUMTYPE 124 +#define ECANCELED 125 +#define ENOKEY 126 +#define EKEYEXPIRED 127 +#define EKEYREVOKED 128 +#define EKEYREJECTED 129 +#define EOWNERDEAD 130 +#define ENOTRECOVERABLE 131 +#define ERFKILL 132 +#define EHWPOISON 133 diff --git a/c/common/test/includes/standard-library/bits/fcntl.h b/c/common/test/includes/standard-library/bits/fcntl.h new file mode 100644 index 0000000000..730a98cfe6 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/fcntl.h @@ -0,0 +1,46 @@ +#define O_CREAT 0100 +#define O_EXCL 0200 +#define O_NOCTTY 0400 +#define O_TRUNC 01000 +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_DSYNC 010000 +#define O_SYNC 04010000 +#define O_RSYNC 04010000 +#define O_DIRECTORY 0200000 +#define O_NOFOLLOW 0400000 +#define O_CLOEXEC 02000000 + +#define O_ASYNC 020000 +#define O_DIRECT 040000 +#define O_LARGEFILE 0100000 +#define O_NOATIME 01000000 +#define O_PATH 010000000 +#define O_TMPFILE 020200000 +#define O_NDELAY O_NONBLOCK + +#define F_DUPFD 0 +#define F_GETFD 1 +#define F_SETFD 2 +#define F_GETFL 3 +#define F_SETFL 4 + +#define F_SETOWN 8 +#define F_GETOWN 9 +#define F_SETSIG 10 +#define F_GETSIG 11 + +#if __LONG_MAX == 0x7fffffffL +#define F_GETLK 12 +#define F_SETLK 13 +#define F_SETLKW 14 +#else +#define F_GETLK 5 +#define F_SETLK 6 +#define F_SETLKW 7 +#endif + +#define F_SETOWN_EX 15 +#define F_GETOWN_EX 16 + +#define F_GETOWNER_UIDS 17 diff --git a/c/common/test/includes/standard-library/bits/fenv.h b/c/common/test/includes/standard-library/bits/fenv.h new file mode 100644 index 0000000000..24df0417f2 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/fenv.h @@ -0,0 +1,34 @@ +#define FE_INVALID 1 +#define __FE_DENORM 2 +#define FE_DIVBYZERO 4 +#define FE_OVERFLOW 8 +#define FE_UNDERFLOW 16 +#define FE_INEXACT 32 + +#define FE_ALL_EXCEPT 63 + +#define FE_TONEAREST 0 +#define FE_DOWNWARD 0x400 +#define FE_UPWARD 0x800 +#define FE_TOWARDZERO 0xc00 + +typedef unsigned short fexcept_t; + +typedef struct { + unsigned short __control_word; + unsigned short __unused1; + unsigned short __status_word; + unsigned short __unused2; + unsigned short __tags; + unsigned short __unused3; + unsigned int __eip; + unsigned short __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short __data_selector; + unsigned short __unused5; + unsigned int __mxcsr; +} fenv_t; + +#define FE_DFL_ENV ((const fenv_t *) -1) diff --git a/c/common/test/includes/standard-library/bits/float.h b/c/common/test/includes/standard-library/bits/float.h new file mode 100644 index 0000000000..4d8e78641b --- /dev/null +++ b/c/common/test/includes/standard-library/bits/float.h @@ -0,0 +1,20 @@ +#ifdef __FLT_EVAL_METHOD__ +#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +#else +#define FLT_EVAL_METHOD 0 +#endif + +#define LDBL_TRUE_MIN 3.6451995318824746025e-4951L +#define LDBL_MIN 3.3621031431120935063e-4932L +#define LDBL_MAX 1.1897314953572317650e+4932L +#define LDBL_EPSILON 1.0842021724855044340e-19L + +#define LDBL_MANT_DIG 64 +#define LDBL_MIN_EXP (-16381) +#define LDBL_MAX_EXP 16384 + +#define LDBL_DIG 18 +#define LDBL_MIN_10_EXP (-4931) +#define LDBL_MAX_10_EXP 4932 + +#define DECIMAL_DIG 21 diff --git a/c/common/test/includes/standard-library/bits/hwcap.h b/c/common/test/includes/standard-library/bits/hwcap.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/common/test/includes/standard-library/bits/io.h b/c/common/test/includes/standard-library/bits/io.h new file mode 100644 index 0000000000..dd5bddc967 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/io.h @@ -0,0 +1,77 @@ +static __inline void outb(unsigned char __val, unsigned short __port) +{ + __asm__ volatile ("outb %0,%1" : : "a" (__val), "dN" (__port)); +} + +static __inline void outw(unsigned short __val, unsigned short __port) +{ + __asm__ volatile ("outw %0,%1" : : "a" (__val), "dN" (__port)); +} + +static __inline void outl(unsigned int __val, unsigned short __port) +{ + __asm__ volatile ("outl %0,%1" : : "a" (__val), "dN" (__port)); +} + +static __inline unsigned char inb(unsigned short __port) +{ + unsigned char __val; + __asm__ volatile ("inb %1,%0" : "=a" (__val) : "dN" (__port)); + return __val; +} + +static __inline unsigned short inw(unsigned short __port) +{ + unsigned short __val; + __asm__ volatile ("inw %1,%0" : "=a" (__val) : "dN" (__port)); + return __val; +} + +static __inline unsigned int inl(unsigned short __port) +{ + unsigned int __val; + __asm__ volatile ("inl %1,%0" : "=a" (__val) : "dN" (__port)); + return __val; +} + +static __inline void outsb(unsigned short __port, const void *__buf, unsigned long __n) +{ + __asm__ volatile ("cld; rep; outsb" + : "+S" (__buf), "+c" (__n) + : "d" (__port)); +} + +static __inline void outsw(unsigned short __port, const void *__buf, unsigned long __n) +{ + __asm__ volatile ("cld; rep; outsw" + : "+S" (__buf), "+c" (__n) + : "d" (__port)); +} + +static __inline void outsl(unsigned short __port, const void *__buf, unsigned long __n) +{ + __asm__ volatile ("cld; rep; outsl" + : "+S" (__buf), "+c"(__n) + : "d" (__port)); +} + +static __inline void insb(unsigned short __port, void *__buf, unsigned long __n) +{ + __asm__ volatile ("cld; rep; insb" + : "+D" (__buf), "+c" (__n) + : "d" (__port)); +} + +static __inline void insw(unsigned short __port, void *__buf, unsigned long __n) +{ + __asm__ volatile ("cld; rep; insw" + : "+D" (__buf), "+c" (__n) + : "d" (__port)); +} + +static __inline void insl(unsigned short __port, void *__buf, unsigned long __n) +{ + __asm__ volatile ("cld; rep; insl" + : "+D" (__buf), "+c" (__n) + : "d" (__port)); +} diff --git a/c/common/test/includes/standard-library/bits/ioctl.h b/c/common/test/includes/standard-library/bits/ioctl.h new file mode 100644 index 0000000000..60ae8b850b --- /dev/null +++ b/c/common/test/includes/standard-library/bits/ioctl.h @@ -0,0 +1,115 @@ +#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) ) +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0) +#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c)) +#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c)) +#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c)) + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 +#define TIOCSBRK 0x5427 +#define TIOCCBRK 0x5428 +#define TIOCGSID 0x5429 +#define TIOCGRS485 0x542E +#define TIOCSRS485 0x542F +#define TIOCGPTN 0x80045430 +#define TIOCSPTLCK 0x40045431 +#define TIOCGDEV 0x80045432 +#define TCGETX 0x5432 +#define TCSETX 0x5433 +#define TCSETXF 0x5434 +#define TCSETXW 0x5435 +#define TIOCSIG 0x40045436 +#define TIOCVHANGUP 0x5437 +#define TIOCGPKT 0x80045438 +#define TIOCGPTLCK 0x80045439 +#define TIOCGEXCL 0x80045440 +#define TIOCGPTPEER 0x5441 +#define TIOCGISO7816 0x80285442 +#define TIOCSISO7816 0xc0285443 + +#define FIONCLEX 0x5450 +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 +#define TIOCSERGETLSR 0x5459 +#define TIOCSERGETMULTI 0x545A +#define TIOCSERSETMULTI 0x545B + +#define TIOCMIWAIT 0x545C +#define TIOCGICOUNT 0x545D +#define FIOQSIZE 0x5460 + +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#if __LONG_MAX == 0x7fffffff +#define SIOCGSTAMP _IOR(0x89, 6, char[16]) +#define SIOCGSTAMPNS _IOR(0x89, 7, char[16]) +#else +#define SIOCGSTAMP 0x8906 +#define SIOCGSTAMPNS 0x8907 +#endif + +#include diff --git a/c/common/test/includes/standard-library/bits/ioctl_fix.h b/c/common/test/includes/standard-library/bits/ioctl_fix.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/common/test/includes/standard-library/bits/ipc.h b/c/common/test/includes/standard-library/bits/ipc.h new file mode 100644 index 0000000000..40d6f3a258 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/ipc.h @@ -0,0 +1,11 @@ +struct ipc_perm { + key_t __ipc_perm_key; + uid_t uid; + gid_t gid; + uid_t cuid; + gid_t cgid; + mode_t mode; + int __ipc_perm_seq; + long __pad1; + long __pad2; +}; diff --git a/c/common/test/includes/standard-library/bits/ipcstat.h b/c/common/test/includes/standard-library/bits/ipcstat.h new file mode 100644 index 0000000000..0018ad1e20 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/ipcstat.h @@ -0,0 +1 @@ +#define IPC_STAT 2 diff --git a/c/common/test/includes/standard-library/bits/kd.h b/c/common/test/includes/standard-library/bits/kd.h new file mode 100644 index 0000000000..33b873f49c --- /dev/null +++ b/c/common/test/includes/standard-library/bits/kd.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/bits/limits.h b/c/common/test/includes/standard-library/bits/limits.h new file mode 100644 index 0000000000..07743b6fd6 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/limits.h @@ -0,0 +1 @@ +#define PAGESIZE 4096 diff --git a/c/common/test/includes/standard-library/bits/link.h b/c/common/test/includes/standard-library/bits/link.h new file mode 100644 index 0000000000..4a94d8f895 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/link.h @@ -0,0 +1 @@ +typedef uint32_t Elf_Symndx; diff --git a/c/common/test/includes/standard-library/bits/mman.h b/c/common/test/includes/standard-library/bits/mman.h new file mode 100644 index 0000000000..ba2d6f7a83 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/mman.h @@ -0,0 +1 @@ +#define MAP_32BIT 0x40 diff --git a/c/common/test/includes/standard-library/bits/msg.h b/c/common/test/includes/standard-library/bits/msg.h new file mode 100644 index 0000000000..2e23ca27f5 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/msg.h @@ -0,0 +1,12 @@ +struct msqid_ds { + struct ipc_perm msg_perm; + time_t msg_stime; + time_t msg_rtime; + time_t msg_ctime; + unsigned long msg_cbytes; + msgqnum_t msg_qnum; + msglen_t msg_qbytes; + pid_t msg_lspid; + pid_t msg_lrpid; + unsigned long __unused[2]; +}; diff --git a/c/common/test/includes/standard-library/bits/poll.h b/c/common/test/includes/standard-library/bits/poll.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/common/test/includes/standard-library/bits/posix.h b/c/common/test/includes/standard-library/bits/posix.h new file mode 100644 index 0000000000..c37b94c142 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/posix.h @@ -0,0 +1,2 @@ +#define _POSIX_V6_LP64_OFF64 1 +#define _POSIX_V7_LP64_OFF64 1 diff --git a/c/common/test/includes/standard-library/bits/ptrace.h b/c/common/test/includes/standard-library/bits/ptrace.h new file mode 100644 index 0000000000..7f8a09b521 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/ptrace.h @@ -0,0 +1,13 @@ +#define PTRACE_GET_THREAD_AREA 25 +#define PTRACE_SET_THREAD_AREA 26 +#define PTRACE_ARCH_PRCTL 30 +#define PTRACE_SYSEMU 31 +#define PTRACE_SYSEMU_SINGLESTEP 32 +#define PTRACE_SINGLEBLOCK 33 + +#define PT_GET_THREAD_AREA PTRACE_GET_THREAD_AREA +#define PT_SET_THREAD_AREA PTRACE_SET_THREAD_AREA +#define PT_ARCH_PRCTL PTRACE_ARCH_PRCTL +#define PT_SYSEMU PTRACE_SYSEMU +#define PT_SYSEMU_SINGLESTEP PTRACE_SYSEMU_SINGLESTEP +#define PT_STEPBLOCK PTRACE_SINGLEBLOCK diff --git a/c/common/test/includes/standard-library/bits/reg.h b/c/common/test/includes/standard-library/bits/reg.h new file mode 100644 index 0000000000..a4df04ced1 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/reg.h @@ -0,0 +1,29 @@ +#undef __WORDSIZE +#define __WORDSIZE 64 +#define R15 0 +#define R14 1 +#define R13 2 +#define R12 3 +#define RBP 4 +#define RBX 5 +#define R11 6 +#define R10 7 +#define R9 8 +#define R8 9 +#define RAX 10 +#define RCX 11 +#define RDX 12 +#define RSI 13 +#define RDI 14 +#define ORIG_RAX 15 +#define RIP 16 +#define CS 17 +#define EFLAGS 18 +#define RSP 19 +#define SS 20 +#define FS_BASE 21 +#define GS_BASE 22 +#define DS 23 +#define ES 24 +#define FS 25 +#define GS 26 diff --git a/c/common/test/includes/standard-library/bits/resource.h b/c/common/test/includes/standard-library/bits/resource.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/common/test/includes/standard-library/bits/sem.h b/c/common/test/includes/standard-library/bits/sem.h new file mode 100644 index 0000000000..e61571c121 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/sem.h @@ -0,0 +1,11 @@ +struct semid_ds { + struct ipc_perm sem_perm; + time_t sem_otime; + long __unused1; + time_t sem_ctime; + long __unused2; + unsigned short sem_nsems; + char __sem_nsems_pad[sizeof(long)-sizeof(short)]; + long __unused3; + long __unused4; +}; diff --git a/c/common/test/includes/standard-library/bits/setjmp.h b/c/common/test/includes/standard-library/bits/setjmp.h new file mode 100644 index 0000000000..63973a8001 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/setjmp.h @@ -0,0 +1 @@ +typedef unsigned long __jmp_buf[8]; diff --git a/c/common/test/includes/standard-library/bits/shm.h b/c/common/test/includes/standard-library/bits/shm.h new file mode 100644 index 0000000000..8d19378191 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/shm.h @@ -0,0 +1,24 @@ +#define SHMLBA 4096 + +struct shmid_ds { + struct ipc_perm shm_perm; + size_t shm_segsz; + time_t shm_atime; + time_t shm_dtime; + time_t shm_ctime; + pid_t shm_cpid; + pid_t shm_lpid; + unsigned long shm_nattch; + unsigned long __pad1; + unsigned long __pad2; +}; + +struct shminfo { + unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4]; +}; + +struct shm_info { + int __used_ids; + unsigned long shm_tot, shm_rss, shm_swp; + unsigned long __swap_attempts, __swap_successes; +}; diff --git a/c/common/test/includes/standard-library/bits/signal.h b/c/common/test/includes/standard-library/bits/signal.h new file mode 100644 index 0000000000..c99317d300 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/signal.h @@ -0,0 +1,153 @@ +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define MINSIGSTKSZ 2048 +#define SIGSTKSZ 8192 +#endif + +#ifdef _GNU_SOURCE +enum { REG_R8 = 0 }; +#define REG_R8 REG_R8 +enum { REG_R9 = 1 }; +#define REG_R9 REG_R9 +enum { REG_R10 = 2 }; +#define REG_R10 REG_R10 +enum { REG_R11 = 3 }; +#define REG_R11 REG_R11 +enum { REG_R12 = 4 }; +#define REG_R12 REG_R12 +enum { REG_R13 = 5 }; +#define REG_R13 REG_R13 +enum { REG_R14 = 6 }; +#define REG_R14 REG_R14 +enum { REG_R15 = 7 }; +#define REG_R15 REG_R15 +enum { REG_RDI = 8 }; +#define REG_RDI REG_RDI +enum { REG_RSI = 9 }; +#define REG_RSI REG_RSI +enum { REG_RBP = 10 }; +#define REG_RBP REG_RBP +enum { REG_RBX = 11 }; +#define REG_RBX REG_RBX +enum { REG_RDX = 12 }; +#define REG_RDX REG_RDX +enum { REG_RAX = 13 }; +#define REG_RAX REG_RAX +enum { REG_RCX = 14 }; +#define REG_RCX REG_RCX +enum { REG_RSP = 15 }; +#define REG_RSP REG_RSP +enum { REG_RIP = 16 }; +#define REG_RIP REG_RIP +enum { REG_EFL = 17 }; +#define REG_EFL REG_EFL +enum { REG_CSGSFS = 18 }; +#define REG_CSGSFS REG_CSGSFS +enum { REG_ERR = 19 }; +#define REG_ERR REG_ERR +enum { REG_TRAPNO = 20 }; +#define REG_TRAPNO REG_TRAPNO +enum { REG_OLDMASK = 21 }; +#define REG_OLDMASK REG_OLDMASK +enum { REG_CR2 = 22 }; +#define REG_CR2 REG_CR2 +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef long long greg_t, gregset_t[23]; +typedef struct _fpstate { + unsigned short cwd, swd, ftw, fop; + unsigned long long rip, rdp; + unsigned mxcsr, mxcr_mask; + struct { + unsigned short significand[4], exponent, padding[3]; + } _st[8]; + struct { + unsigned element[4]; + } _xmm[16]; + unsigned padding[24]; +} *fpregset_t; +struct sigcontext { + unsigned long r8, r9, r10, r11, r12, r13, r14, r15; + unsigned long rdi, rsi, rbp, rbx, rdx, rax, rcx, rsp, rip, eflags; + unsigned short cs, gs, fs, __pad0; + unsigned long err, trapno, oldmask, cr2; + struct _fpstate *fpstate; + unsigned long __reserved1[8]; +}; +typedef struct { + gregset_t gregs; + fpregset_t fpregs; + unsigned long long __reserved1[8]; +} mcontext_t; +#else +typedef struct { + unsigned long __space[32]; +} mcontext_t; +#endif + +struct sigaltstack { + void *ss_sp; + int ss_flags; + size_t ss_size; +}; + +typedef struct __ucontext { + unsigned long uc_flags; + struct __ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; + unsigned long __fpregs_mem[64]; +} ucontext_t; + +#define SA_NOCLDSTOP 1 +#define SA_NOCLDWAIT 2 +#define SA_SIGINFO 4 +#define SA_ONSTACK 0x08000000 +#define SA_RESTART 0x10000000 +#define SA_NODEFER 0x40000000 +#define SA_RESETHAND 0x80000000 +#define SA_RESTORER 0x04000000 + +#endif + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT SIGABRT +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL 29 +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED SIGSYS + +#define _NSIG 65 + diff --git a/c/common/test/includes/standard-library/bits/socket.h b/c/common/test/includes/standard-library/bits/socket.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/common/test/includes/standard-library/bits/soundcard.h b/c/common/test/includes/standard-library/bits/soundcard.h new file mode 100644 index 0000000000..fade986fe4 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/soundcard.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/bits/stat.h b/c/common/test/includes/standard-library/bits/stat.h new file mode 100644 index 0000000000..081237c32a --- /dev/null +++ b/c/common/test/includes/standard-library/bits/stat.h @@ -0,0 +1,22 @@ +/* copied from kernel definition, but with padding replaced + * by the corresponding correctly-sized userspace types. */ + +struct stat { + dev_t st_dev; + ino_t st_ino; + nlink_t st_nlink; + + mode_t st_mode; + uid_t st_uid; + gid_t st_gid; + unsigned int __pad0; + dev_t st_rdev; + off_t st_size; + blksize_t st_blksize; + blkcnt_t st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; diff --git a/c/common/test/includes/standard-library/bits/statfs.h b/c/common/test/includes/standard-library/bits/statfs.h new file mode 100644 index 0000000000..f103f4e4f4 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/statfs.h @@ -0,0 +1,7 @@ +struct statfs { + unsigned long f_type, f_bsize; + fsblkcnt_t f_blocks, f_bfree, f_bavail; + fsfilcnt_t f_files, f_ffree; + fsid_t f_fsid; + unsigned long f_namelen, f_frsize, f_flags, f_spare[4]; +}; diff --git a/c/common/test/includes/standard-library/bits/stdint.h b/c/common/test/includes/standard-library/bits/stdint.h new file mode 100644 index 0000000000..1bb147f24e --- /dev/null +++ b/c/common/test/includes/standard-library/bits/stdint.h @@ -0,0 +1,20 @@ +typedef int32_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef uint32_t uint_fast16_t; +typedef uint32_t uint_fast32_t; + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN + +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX + +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#define SIZE_MAX UINT64_MAX diff --git a/c/common/test/includes/standard-library/bits/syscall.h b/c/common/test/includes/standard-library/bits/syscall.h new file mode 100644 index 0000000000..0df452c36c --- /dev/null +++ b/c/common/test/includes/standard-library/bits/syscall.h @@ -0,0 +1,703 @@ +#define __NR_read 0 +#define __NR_write 1 +#define __NR_open 2 +#define __NR_close 3 +#define __NR_stat 4 +#define __NR_fstat 5 +#define __NR_lstat 6 +#define __NR_poll 7 +#define __NR_lseek 8 +#define __NR_mmap 9 +#define __NR_mprotect 10 +#define __NR_munmap 11 +#define __NR_brk 12 +#define __NR_rt_sigaction 13 +#define __NR_rt_sigprocmask 14 +#define __NR_rt_sigreturn 15 +#define __NR_ioctl 16 +#define __NR_pread64 17 +#define __NR_pwrite64 18 +#define __NR_readv 19 +#define __NR_writev 20 +#define __NR_access 21 +#define __NR_pipe 22 +#define __NR_select 23 +#define __NR_sched_yield 24 +#define __NR_mremap 25 +#define __NR_msync 26 +#define __NR_mincore 27 +#define __NR_madvise 28 +#define __NR_shmget 29 +#define __NR_shmat 30 +#define __NR_shmctl 31 +#define __NR_dup 32 +#define __NR_dup2 33 +#define __NR_pause 34 +#define __NR_nanosleep 35 +#define __NR_getitimer 36 +#define __NR_alarm 37 +#define __NR_setitimer 38 +#define __NR_getpid 39 +#define __NR_sendfile 40 +#define __NR_socket 41 +#define __NR_connect 42 +#define __NR_accept 43 +#define __NR_sendto 44 +#define __NR_recvfrom 45 +#define __NR_sendmsg 46 +#define __NR_recvmsg 47 +#define __NR_shutdown 48 +#define __NR_bind 49 +#define __NR_listen 50 +#define __NR_getsockname 51 +#define __NR_getpeername 52 +#define __NR_socketpair 53 +#define __NR_setsockopt 54 +#define __NR_getsockopt 55 +#define __NR_clone 56 +#define __NR_fork 57 +#define __NR_vfork 58 +#define __NR_execve 59 +#define __NR_exit 60 +#define __NR_wait4 61 +#define __NR_kill 62 +#define __NR_uname 63 +#define __NR_semget 64 +#define __NR_semop 65 +#define __NR_semctl 66 +#define __NR_shmdt 67 +#define __NR_msgget 68 +#define __NR_msgsnd 69 +#define __NR_msgrcv 70 +#define __NR_msgctl 71 +#define __NR_fcntl 72 +#define __NR_flock 73 +#define __NR_fsync 74 +#define __NR_fdatasync 75 +#define __NR_truncate 76 +#define __NR_ftruncate 77 +#define __NR_getdents 78 +#define __NR_getcwd 79 +#define __NR_chdir 80 +#define __NR_fchdir 81 +#define __NR_rename 82 +#define __NR_mkdir 83 +#define __NR_rmdir 84 +#define __NR_creat 85 +#define __NR_link 86 +#define __NR_unlink 87 +#define __NR_symlink 88 +#define __NR_readlink 89 +#define __NR_chmod 90 +#define __NR_fchmod 91 +#define __NR_chown 92 +#define __NR_fchown 93 +#define __NR_lchown 94 +#define __NR_umask 95 +#define __NR_gettimeofday 96 +#define __NR_getrlimit 97 +#define __NR_getrusage 98 +#define __NR_sysinfo 99 +#define __NR_times 100 +#define __NR_ptrace 101 +#define __NR_getuid 102 +#define __NR_syslog 103 +#define __NR_getgid 104 +#define __NR_setuid 105 +#define __NR_setgid 106 +#define __NR_geteuid 107 +#define __NR_getegid 108 +#define __NR_setpgid 109 +#define __NR_getppid 110 +#define __NR_getpgrp 111 +#define __NR_setsid 112 +#define __NR_setreuid 113 +#define __NR_setregid 114 +#define __NR_getgroups 115 +#define __NR_setgroups 116 +#define __NR_setresuid 117 +#define __NR_getresuid 118 +#define __NR_setresgid 119 +#define __NR_getresgid 120 +#define __NR_getpgid 121 +#define __NR_setfsuid 122 +#define __NR_setfsgid 123 +#define __NR_getsid 124 +#define __NR_capget 125 +#define __NR_capset 126 +#define __NR_rt_sigpending 127 +#define __NR_rt_sigtimedwait 128 +#define __NR_rt_sigqueueinfo 129 +#define __NR_rt_sigsuspend 130 +#define __NR_sigaltstack 131 +#define __NR_utime 132 +#define __NR_mknod 133 +#define __NR_uselib 134 +#define __NR_personality 135 +#define __NR_ustat 136 +#define __NR_statfs 137 +#define __NR_fstatfs 138 +#define __NR_sysfs 139 +#define __NR_getpriority 140 +#define __NR_setpriority 141 +#define __NR_sched_setparam 142 +#define __NR_sched_getparam 143 +#define __NR_sched_setscheduler 144 +#define __NR_sched_getscheduler 145 +#define __NR_sched_get_priority_max 146 +#define __NR_sched_get_priority_min 147 +#define __NR_sched_rr_get_interval 148 +#define __NR_mlock 149 +#define __NR_munlock 150 +#define __NR_mlockall 151 +#define __NR_munlockall 152 +#define __NR_vhangup 153 +#define __NR_modify_ldt 154 +#define __NR_pivot_root 155 +#define __NR__sysctl 156 +#define __NR_prctl 157 +#define __NR_arch_prctl 158 +#define __NR_adjtimex 159 +#define __NR_setrlimit 160 +#define __NR_chroot 161 +#define __NR_sync 162 +#define __NR_acct 163 +#define __NR_settimeofday 164 +#define __NR_mount 165 +#define __NR_umount2 166 +#define __NR_swapon 167 +#define __NR_swapoff 168 +#define __NR_reboot 169 +#define __NR_sethostname 170 +#define __NR_setdomainname 171 +#define __NR_iopl 172 +#define __NR_ioperm 173 +#define __NR_create_module 174 +#define __NR_init_module 175 +#define __NR_delete_module 176 +#define __NR_get_kernel_syms 177 +#define __NR_query_module 178 +#define __NR_quotactl 179 +#define __NR_nfsservctl 180 +#define __NR_getpmsg 181 +#define __NR_putpmsg 182 +#define __NR_afs_syscall 183 +#define __NR_tuxcall 184 +#define __NR_security 185 +#define __NR_gettid 186 +#define __NR_readahead 187 +#define __NR_setxattr 188 +#define __NR_lsetxattr 189 +#define __NR_fsetxattr 190 +#define __NR_getxattr 191 +#define __NR_lgetxattr 192 +#define __NR_fgetxattr 193 +#define __NR_listxattr 194 +#define __NR_llistxattr 195 +#define __NR_flistxattr 196 +#define __NR_removexattr 197 +#define __NR_lremovexattr 198 +#define __NR_fremovexattr 199 +#define __NR_tkill 200 +#define __NR_time 201 +#define __NR_futex 202 +#define __NR_sched_setaffinity 203 +#define __NR_sched_getaffinity 204 +#define __NR_set_thread_area 205 +#define __NR_io_setup 206 +#define __NR_io_destroy 207 +#define __NR_io_getevents 208 +#define __NR_io_submit 209 +#define __NR_io_cancel 210 +#define __NR_get_thread_area 211 +#define __NR_lookup_dcookie 212 +#define __NR_epoll_create 213 +#define __NR_epoll_ctl_old 214 +#define __NR_epoll_wait_old 215 +#define __NR_remap_file_pages 216 +#define __NR_getdents64 217 +#define __NR_set_tid_address 218 +#define __NR_restart_syscall 219 +#define __NR_semtimedop 220 +#define __NR_fadvise64 221 +#define __NR_timer_create 222 +#define __NR_timer_settime 223 +#define __NR_timer_gettime 224 +#define __NR_timer_getoverrun 225 +#define __NR_timer_delete 226 +#define __NR_clock_settime 227 +#define __NR_clock_gettime 228 +#define __NR_clock_getres 229 +#define __NR_clock_nanosleep 230 +#define __NR_exit_group 231 +#define __NR_epoll_wait 232 +#define __NR_epoll_ctl 233 +#define __NR_tgkill 234 +#define __NR_utimes 235 +#define __NR_vserver 236 +#define __NR_mbind 237 +#define __NR_set_mempolicy 238 +#define __NR_get_mempolicy 239 +#define __NR_mq_open 240 +#define __NR_mq_unlink 241 +#define __NR_mq_timedsend 242 +#define __NR_mq_timedreceive 243 +#define __NR_mq_notify 244 +#define __NR_mq_getsetattr 245 +#define __NR_kexec_load 246 +#define __NR_waitid 247 +#define __NR_add_key 248 +#define __NR_request_key 249 +#define __NR_keyctl 250 +#define __NR_ioprio_set 251 +#define __NR_ioprio_get 252 +#define __NR_inotify_init 253 +#define __NR_inotify_add_watch 254 +#define __NR_inotify_rm_watch 255 +#define __NR_migrate_pages 256 +#define __NR_openat 257 +#define __NR_mkdirat 258 +#define __NR_mknodat 259 +#define __NR_fchownat 260 +#define __NR_futimesat 261 +#define __NR_newfstatat 262 +#define __NR_unlinkat 263 +#define __NR_renameat 264 +#define __NR_linkat 265 +#define __NR_symlinkat 266 +#define __NR_readlinkat 267 +#define __NR_fchmodat 268 +#define __NR_faccessat 269 +#define __NR_pselect6 270 +#define __NR_ppoll 271 +#define __NR_unshare 272 +#define __NR_set_robust_list 273 +#define __NR_get_robust_list 274 +#define __NR_splice 275 +#define __NR_tee 276 +#define __NR_sync_file_range 277 +#define __NR_vmsplice 278 +#define __NR_move_pages 279 +#define __NR_utimensat 280 +#define __NR_epoll_pwait 281 +#define __NR_signalfd 282 +#define __NR_timerfd_create 283 +#define __NR_eventfd 284 +#define __NR_fallocate 285 +#define __NR_timerfd_settime 286 +#define __NR_timerfd_gettime 287 +#define __NR_accept4 288 +#define __NR_signalfd4 289 +#define __NR_eventfd2 290 +#define __NR_epoll_create1 291 +#define __NR_dup3 292 +#define __NR_pipe2 293 +#define __NR_inotify_init1 294 +#define __NR_preadv 295 +#define __NR_pwritev 296 +#define __NR_rt_tgsigqueueinfo 297 +#define __NR_perf_event_open 298 +#define __NR_recvmmsg 299 +#define __NR_fanotify_init 300 +#define __NR_fanotify_mark 301 +#define __NR_prlimit64 302 +#define __NR_name_to_handle_at 303 +#define __NR_open_by_handle_at 304 +#define __NR_clock_adjtime 305 +#define __NR_syncfs 306 +#define __NR_sendmmsg 307 +#define __NR_setns 308 +#define __NR_getcpu 309 +#define __NR_process_vm_readv 310 +#define __NR_process_vm_writev 311 +#define __NR_kcmp 312 +#define __NR_finit_module 313 +#define __NR_sched_setattr 314 +#define __NR_sched_getattr 315 +#define __NR_renameat2 316 +#define __NR_seccomp 317 +#define __NR_getrandom 318 +#define __NR_memfd_create 319 +#define __NR_kexec_file_load 320 +#define __NR_bpf 321 +#define __NR_execveat 322 +#define __NR_userfaultfd 323 +#define __NR_membarrier 324 +#define __NR_mlock2 325 +#define __NR_copy_file_range 326 +#define __NR_preadv2 327 +#define __NR_pwritev2 328 +#define __NR_pkey_mprotect 329 +#define __NR_pkey_alloc 330 +#define __NR_pkey_free 331 +#define __NR_statx 332 +#define __NR_io_pgetevents 333 +#define __NR_rseq 334 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 + +#define SYS_read 0 +#define SYS_write 1 +#define SYS_open 2 +#define SYS_close 3 +#define SYS_stat 4 +#define SYS_fstat 5 +#define SYS_lstat 6 +#define SYS_poll 7 +#define SYS_lseek 8 +#define SYS_mmap 9 +#define SYS_mprotect 10 +#define SYS_munmap 11 +#define SYS_brk 12 +#define SYS_rt_sigaction 13 +#define SYS_rt_sigprocmask 14 +#define SYS_rt_sigreturn 15 +#define SYS_ioctl 16 +#define SYS_pread64 17 +#define SYS_pwrite64 18 +#define SYS_readv 19 +#define SYS_writev 20 +#define SYS_access 21 +#define SYS_pipe 22 +#define SYS_select 23 +#define SYS_sched_yield 24 +#define SYS_mremap 25 +#define SYS_msync 26 +#define SYS_mincore 27 +#define SYS_madvise 28 +#define SYS_shmget 29 +#define SYS_shmat 30 +#define SYS_shmctl 31 +#define SYS_dup 32 +#define SYS_dup2 33 +#define SYS_pause 34 +#define SYS_nanosleep 35 +#define SYS_getitimer 36 +#define SYS_alarm 37 +#define SYS_setitimer 38 +#define SYS_getpid 39 +#define SYS_sendfile 40 +#define SYS_socket 41 +#define SYS_connect 42 +#define SYS_accept 43 +#define SYS_sendto 44 +#define SYS_recvfrom 45 +#define SYS_sendmsg 46 +#define SYS_recvmsg 47 +#define SYS_shutdown 48 +#define SYS_bind 49 +#define SYS_listen 50 +#define SYS_getsockname 51 +#define SYS_getpeername 52 +#define SYS_socketpair 53 +#define SYS_setsockopt 54 +#define SYS_getsockopt 55 +#define SYS_clone 56 +#define SYS_fork 57 +#define SYS_vfork 58 +#define SYS_execve 59 +#define SYS_exit 60 +#define SYS_wait4 61 +#define SYS_kill 62 +#define SYS_uname 63 +#define SYS_semget 64 +#define SYS_semop 65 +#define SYS_semctl 66 +#define SYS_shmdt 67 +#define SYS_msgget 68 +#define SYS_msgsnd 69 +#define SYS_msgrcv 70 +#define SYS_msgctl 71 +#define SYS_fcntl 72 +#define SYS_flock 73 +#define SYS_fsync 74 +#define SYS_fdatasync 75 +#define SYS_truncate 76 +#define SYS_ftruncate 77 +#define SYS_getdents 78 +#define SYS_getcwd 79 +#define SYS_chdir 80 +#define SYS_fchdir 81 +#define SYS_rename 82 +#define SYS_mkdir 83 +#define SYS_rmdir 84 +#define SYS_creat 85 +#define SYS_link 86 +#define SYS_unlink 87 +#define SYS_symlink 88 +#define SYS_readlink 89 +#define SYS_chmod 90 +#define SYS_fchmod 91 +#define SYS_chown 92 +#define SYS_fchown 93 +#define SYS_lchown 94 +#define SYS_umask 95 +#define SYS_gettimeofday 96 +#define SYS_getrlimit 97 +#define SYS_getrusage 98 +#define SYS_sysinfo 99 +#define SYS_times 100 +#define SYS_ptrace 101 +#define SYS_getuid 102 +#define SYS_syslog 103 +#define SYS_getgid 104 +#define SYS_setuid 105 +#define SYS_setgid 106 +#define SYS_geteuid 107 +#define SYS_getegid 108 +#define SYS_setpgid 109 +#define SYS_getppid 110 +#define SYS_getpgrp 111 +#define SYS_setsid 112 +#define SYS_setreuid 113 +#define SYS_setregid 114 +#define SYS_getgroups 115 +#define SYS_setgroups 116 +#define SYS_setresuid 117 +#define SYS_getresuid 118 +#define SYS_setresgid 119 +#define SYS_getresgid 120 +#define SYS_getpgid 121 +#define SYS_setfsuid 122 +#define SYS_setfsgid 123 +#define SYS_getsid 124 +#define SYS_capget 125 +#define SYS_capset 126 +#define SYS_rt_sigpending 127 +#define SYS_rt_sigtimedwait 128 +#define SYS_rt_sigqueueinfo 129 +#define SYS_rt_sigsuspend 130 +#define SYS_sigaltstack 131 +#define SYS_utime 132 +#define SYS_mknod 133 +#define SYS_uselib 134 +#define SYS_personality 135 +#define SYS_ustat 136 +#define SYS_statfs 137 +#define SYS_fstatfs 138 +#define SYS_sysfs 139 +#define SYS_getpriority 140 +#define SYS_setpriority 141 +#define SYS_sched_setparam 142 +#define SYS_sched_getparam 143 +#define SYS_sched_setscheduler 144 +#define SYS_sched_getscheduler 145 +#define SYS_sched_get_priority_max 146 +#define SYS_sched_get_priority_min 147 +#define SYS_sched_rr_get_interval 148 +#define SYS_mlock 149 +#define SYS_munlock 150 +#define SYS_mlockall 151 +#define SYS_munlockall 152 +#define SYS_vhangup 153 +#define SYS_modify_ldt 154 +#define SYS_pivot_root 155 +#define SYS__sysctl 156 +#define SYS_prctl 157 +#define SYS_arch_prctl 158 +#define SYS_adjtimex 159 +#define SYS_setrlimit 160 +#define SYS_chroot 161 +#define SYS_sync 162 +#define SYS_acct 163 +#define SYS_settimeofday 164 +#define SYS_mount 165 +#define SYS_umount2 166 +#define SYS_swapon 167 +#define SYS_swapoff 168 +#define SYS_reboot 169 +#define SYS_sethostname 170 +#define SYS_setdomainname 171 +#define SYS_iopl 172 +#define SYS_ioperm 173 +#define SYS_create_module 174 +#define SYS_init_module 175 +#define SYS_delete_module 176 +#define SYS_get_kernel_syms 177 +#define SYS_query_module 178 +#define SYS_quotactl 179 +#define SYS_nfsservctl 180 +#define SYS_getpmsg 181 +#define SYS_putpmsg 182 +#define SYS_afs_syscall 183 +#define SYS_tuxcall 184 +#define SYS_security 185 +#define SYS_gettid 186 +#define SYS_readahead 187 +#define SYS_setxattr 188 +#define SYS_lsetxattr 189 +#define SYS_fsetxattr 190 +#define SYS_getxattr 191 +#define SYS_lgetxattr 192 +#define SYS_fgetxattr 193 +#define SYS_listxattr 194 +#define SYS_llistxattr 195 +#define SYS_flistxattr 196 +#define SYS_removexattr 197 +#define SYS_lremovexattr 198 +#define SYS_fremovexattr 199 +#define SYS_tkill 200 +#define SYS_time 201 +#define SYS_futex 202 +#define SYS_sched_setaffinity 203 +#define SYS_sched_getaffinity 204 +#define SYS_set_thread_area 205 +#define SYS_io_setup 206 +#define SYS_io_destroy 207 +#define SYS_io_getevents 208 +#define SYS_io_submit 209 +#define SYS_io_cancel 210 +#define SYS_get_thread_area 211 +#define SYS_lookup_dcookie 212 +#define SYS_epoll_create 213 +#define SYS_epoll_ctl_old 214 +#define SYS_epoll_wait_old 215 +#define SYS_remap_file_pages 216 +#define SYS_getdents64 217 +#define SYS_set_tid_address 218 +#define SYS_restart_syscall 219 +#define SYS_semtimedop 220 +#define SYS_fadvise64 221 +#define SYS_timer_create 222 +#define SYS_timer_settime 223 +#define SYS_timer_gettime 224 +#define SYS_timer_getoverrun 225 +#define SYS_timer_delete 226 +#define SYS_clock_settime 227 +#define SYS_clock_gettime 228 +#define SYS_clock_getres 229 +#define SYS_clock_nanosleep 230 +#define SYS_exit_group 231 +#define SYS_epoll_wait 232 +#define SYS_epoll_ctl 233 +#define SYS_tgkill 234 +#define SYS_utimes 235 +#define SYS_vserver 236 +#define SYS_mbind 237 +#define SYS_set_mempolicy 238 +#define SYS_get_mempolicy 239 +#define SYS_mq_open 240 +#define SYS_mq_unlink 241 +#define SYS_mq_timedsend 242 +#define SYS_mq_timedreceive 243 +#define SYS_mq_notify 244 +#define SYS_mq_getsetattr 245 +#define SYS_kexec_load 246 +#define SYS_waitid 247 +#define SYS_add_key 248 +#define SYS_request_key 249 +#define SYS_keyctl 250 +#define SYS_ioprio_set 251 +#define SYS_ioprio_get 252 +#define SYS_inotify_init 253 +#define SYS_inotify_add_watch 254 +#define SYS_inotify_rm_watch 255 +#define SYS_migrate_pages 256 +#define SYS_openat 257 +#define SYS_mkdirat 258 +#define SYS_mknodat 259 +#define SYS_fchownat 260 +#define SYS_futimesat 261 +#define SYS_newfstatat 262 +#define SYS_unlinkat 263 +#define SYS_renameat 264 +#define SYS_linkat 265 +#define SYS_symlinkat 266 +#define SYS_readlinkat 267 +#define SYS_fchmodat 268 +#define SYS_faccessat 269 +#define SYS_pselect6 270 +#define SYS_ppoll 271 +#define SYS_unshare 272 +#define SYS_set_robust_list 273 +#define SYS_get_robust_list 274 +#define SYS_splice 275 +#define SYS_tee 276 +#define SYS_sync_file_range 277 +#define SYS_vmsplice 278 +#define SYS_move_pages 279 +#define SYS_utimensat 280 +#define SYS_epoll_pwait 281 +#define SYS_signalfd 282 +#define SYS_timerfd_create 283 +#define SYS_eventfd 284 +#define SYS_fallocate 285 +#define SYS_timerfd_settime 286 +#define SYS_timerfd_gettime 287 +#define SYS_accept4 288 +#define SYS_signalfd4 289 +#define SYS_eventfd2 290 +#define SYS_epoll_create1 291 +#define SYS_dup3 292 +#define SYS_pipe2 293 +#define SYS_inotify_init1 294 +#define SYS_preadv 295 +#define SYS_pwritev 296 +#define SYS_rt_tgsigqueueinfo 297 +#define SYS_perf_event_open 298 +#define SYS_recvmmsg 299 +#define SYS_fanotify_init 300 +#define SYS_fanotify_mark 301 +#define SYS_prlimit64 302 +#define SYS_name_to_handle_at 303 +#define SYS_open_by_handle_at 304 +#define SYS_clock_adjtime 305 +#define SYS_syncfs 306 +#define SYS_sendmmsg 307 +#define SYS_setns 308 +#define SYS_getcpu 309 +#define SYS_process_vm_readv 310 +#define SYS_process_vm_writev 311 +#define SYS_kcmp 312 +#define SYS_finit_module 313 +#define SYS_sched_setattr 314 +#define SYS_sched_getattr 315 +#define SYS_renameat2 316 +#define SYS_seccomp 317 +#define SYS_getrandom 318 +#define SYS_memfd_create 319 +#define SYS_kexec_file_load 320 +#define SYS_bpf 321 +#define SYS_execveat 322 +#define SYS_userfaultfd 323 +#define SYS_membarrier 324 +#define SYS_mlock2 325 +#define SYS_copy_file_range 326 +#define SYS_preadv2 327 +#define SYS_pwritev2 328 +#define SYS_pkey_mprotect 329 +#define SYS_pkey_alloc 330 +#define SYS_pkey_free 331 +#define SYS_statx 332 +#define SYS_io_pgetevents 333 +#define SYS_rseq 334 +#define SYS_pidfd_send_signal 424 +#define SYS_io_uring_setup 425 +#define SYS_io_uring_enter 426 +#define SYS_io_uring_register 427 +#define SYS_open_tree 428 +#define SYS_move_mount 429 +#define SYS_fsopen 430 +#define SYS_fsconfig 431 +#define SYS_fsmount 432 +#define SYS_fspick 433 +#define SYS_pidfd_open 434 +#define SYS_clone3 435 +#define SYS_close_range 436 +#define SYS_openat2 437 +#define SYS_pidfd_getfd 438 +#define SYS_faccessat2 439 diff --git a/c/common/test/includes/standard-library/bits/termios.h b/c/common/test/includes/standard-library/bits/termios.h new file mode 100644 index 0000000000..124f71d201 --- /dev/null +++ b/c/common/test/includes/standard-library/bits/termios.h @@ -0,0 +1,166 @@ +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_line; + cc_t c_cc[NCCS]; + speed_t __c_ispeed; + speed_t __c_ospeed; +}; + +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#define B0 0000000 +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 + +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 + +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 + +#define ISIG 0000001 +#define ICANON 0000002 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define IEXTEN 0100000 + +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define EXTA 0000016 +#define EXTB 0000017 +#define CBAUD 0010017 +#define CBAUDEX 0010000 +#define CIBAUD 002003600000 +#define CMSPAR 010000000000 +#define CRTSCTS 020000000000 + +#define XCASE 0000004 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define EXTPROC 0200000 + +#define XTABS 0014000 +#endif diff --git a/c/common/test/includes/standard-library/bits/user.h b/c/common/test/includes/standard-library/bits/user.h new file mode 100644 index 0000000000..4073cc06ff --- /dev/null +++ b/c/common/test/includes/standard-library/bits/user.h @@ -0,0 +1,41 @@ +#undef __WORDSIZE +#define __WORDSIZE 64 + +typedef struct user_fpregs_struct { + uint16_t cwd, swd, ftw, fop; + uint64_t rip, rdp; + uint32_t mxcsr, mxcr_mask; + uint32_t st_space[32], xmm_space[64], padding[24]; +} elf_fpregset_t; + +struct user_regs_struct { + unsigned long r15, r14, r13, r12, rbp, rbx, r11, r10, r9, r8; + unsigned long rax, rcx, rdx, rsi, rdi, orig_rax, rip; + unsigned long cs, eflags, rsp, ss, fs_base, gs_base, ds, es, fs, gs; +}; +#define ELF_NGREG 27 +typedef unsigned long long elf_greg_t, elf_gregset_t[ELF_NGREG]; + +struct user { + struct user_regs_struct regs; + int u_fpvalid; + struct user_fpregs_struct i387; + unsigned long u_tsize; + unsigned long u_dsize; + unsigned long u_ssize; + unsigned long start_code; + unsigned long start_stack; + long signal; + int reserved; + struct user_regs_struct *u_ar0; + struct user_fpregs_struct *u_fpstate; + unsigned long magic; + char u_comm[32]; + unsigned long u_debugreg[8]; +}; + +#define PAGE_MASK (~(PAGESIZE-1)) +#define NBPG PAGESIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) diff --git a/c/common/test/includes/standard-library/bits/vt.h b/c/common/test/includes/standard-library/bits/vt.h new file mode 100644 index 0000000000..834abfbc8f --- /dev/null +++ b/c/common/test/includes/standard-library/bits/vt.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/byteswap.h b/c/common/test/includes/standard-library/byteswap.h new file mode 100644 index 0000000000..00b9df3c9f --- /dev/null +++ b/c/common/test/includes/standard-library/byteswap.h @@ -0,0 +1,26 @@ +#ifndef _BYTESWAP_H +#define _BYTESWAP_H + +#include +#include + +static __inline uint16_t __bswap_16(uint16_t __x) +{ + return __x<<8 | __x>>8; +} + +static __inline uint32_t __bswap_32(uint32_t __x) +{ + return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; +} + +static __inline uint64_t __bswap_64(uint64_t __x) +{ + return __bswap_32(__x)+0ULL<<32 | __bswap_32(__x>>32); +} + +#define bswap_16(x) __bswap_16(x) +#define bswap_32(x) __bswap_32(x) +#define bswap_64(x) __bswap_64(x) + +#endif diff --git a/c/common/test/includes/standard-library/complex.h b/c/common/test/includes/standard-library/complex.h new file mode 100644 index 0000000000..008b3c7e3b --- /dev/null +++ b/c/common/test/includes/standard-library/complex.h @@ -0,0 +1,133 @@ +#ifndef _COMPLEX_H +#define _COMPLEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define complex _Complex +#ifdef __GNUC__ +#define _Complex_I (__extension__ (0.0f+1.0fi)) +#else +#define _Complex_I (0.0f+1.0fi) +#endif +#define I _Complex_I + +double complex cacos(double complex); +float complex cacosf(float complex); +long double complex cacosl(long double complex); + +double complex casin(double complex); +float complex casinf(float complex); +long double complex casinl(long double complex); + +double complex catan(double complex); +float complex catanf(float complex); +long double complex catanl(long double complex); + +double complex ccos(double complex); +float complex ccosf(float complex); +long double complex ccosl(long double complex); + +double complex csin(double complex); +float complex csinf(float complex); +long double complex csinl(long double complex); + +double complex ctan(double complex); +float complex ctanf(float complex); +long double complex ctanl(long double complex); + +double complex cacosh(double complex); +float complex cacoshf(float complex); +long double complex cacoshl(long double complex); + +double complex casinh(double complex); +float complex casinhf(float complex); +long double complex casinhl(long double complex); + +double complex catanh(double complex); +float complex catanhf(float complex); +long double complex catanhl(long double complex); + +double complex ccosh(double complex); +float complex ccoshf(float complex); +long double complex ccoshl(long double complex); + +double complex csinh(double complex); +float complex csinhf(float complex); +long double complex csinhl(long double complex); + +double complex ctanh(double complex); +float complex ctanhf(float complex); +long double complex ctanhl(long double complex); + +double complex cexp(double complex); +float complex cexpf(float complex); +long double complex cexpl(long double complex); + +double complex clog(double complex); +float complex clogf(float complex); +long double complex clogl(long double complex); + +double cabs(double complex); +float cabsf(float complex); +long double cabsl(long double complex); + +double complex cpow(double complex, double complex); +float complex cpowf(float complex, float complex); +long double complex cpowl(long double complex, long double complex); + +double complex csqrt(double complex); +float complex csqrtf(float complex); +long double complex csqrtl(long double complex); + +double carg(double complex); +float cargf(float complex); +long double cargl(long double complex); + +double cimag(double complex); +float cimagf(float complex); +long double cimagl(long double complex); + +double complex conj(double complex); +float complex conjf(float complex); +long double complex conjl(long double complex); + +double complex cproj(double complex); +float complex cprojf(float complex); +long double complex cprojl(long double complex); + +double creal(double complex); +float crealf(float complex); +long double creall(long double complex); + +#ifndef __cplusplus +#define __CIMAG(x, t) \ + (+(union { _Complex t __z; t __xy[2]; }){(_Complex t)(x)}.__xy[1]) + +#define creal(x) ((double)(x)) +#define crealf(x) ((float)(x)) +#define creall(x) ((long double)(x)) + +#define cimag(x) __CIMAG(x, double) +#define cimagf(x) __CIMAG(x, float) +#define cimagl(x) __CIMAG(x, long double) +#endif + +#if __STDC_VERSION__ >= 201112L +#if defined(_Imaginary_I) +#define __CMPLX(x, y, t) ((t)(x) + _Imaginary_I*(t)(y)) +#elif defined(__clang__) +#define __CMPLX(x, y, t) (+(_Complex t){ (t)(x), (t)(y) }) +#else +#define __CMPLX(x, y, t) (__builtin_complex((t)(x), (t)(y))) +#endif +#define CMPLX(x, y) __CMPLX(x, y, double) +#define CMPLXF(x, y) __CMPLX(x, y, float) +#define CMPLXL(x, y) __CMPLX(x, y, long double) +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/cpio.h b/c/common/test/includes/standard-library/cpio.h new file mode 100644 index 0000000000..39a1f8bba5 --- /dev/null +++ b/c/common/test/includes/standard-library/cpio.h @@ -0,0 +1,29 @@ +#ifndef _CPIO_H +#define _CPIO_H + +#define MAGIC "070707" + +#define C_IRUSR 000400 +#define C_IWUSR 000200 +#define C_IXUSR 000100 +#define C_IRGRP 000040 +#define C_IWGRP 000020 +#define C_IXGRP 000010 +#define C_IROTH 000004 +#define C_IWOTH 000002 +#define C_IXOTH 000001 + +#define C_ISUID 004000 +#define C_ISGID 002000 +#define C_ISVTX 001000 + +#define C_ISBLK 060000 +#define C_ISCHR 020000 +#define C_ISDIR 040000 +#define C_ISFIFO 010000 +#define C_ISSOCK 0140000 +#define C_ISLNK 0120000 +#define C_ISCTG 0110000 +#define C_ISREG 0100000 + +#endif diff --git a/c/common/test/includes/standard-library/crypt.h b/c/common/test/includes/standard-library/crypt.h new file mode 100644 index 0000000000..07de21698c --- /dev/null +++ b/c/common/test/includes/standard-library/crypt.h @@ -0,0 +1,20 @@ +#ifndef _CRYPT_H +#define _CRYPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct crypt_data { + int initialized; + char __buf[256]; +}; + +char *crypt(const char *, const char *); +char *crypt_r(const char *, const char *, struct crypt_data *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/ctype.h b/c/common/test/includes/standard-library/ctype.h new file mode 100644 index 0000000000..7936536f57 --- /dev/null +++ b/c/common/test/includes/standard-library/ctype.h @@ -0,0 +1,75 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int isalnum(int); +int isalpha(int); +int isblank(int); +int iscntrl(int); +int isdigit(int); +int isgraph(int); +int islower(int); +int isprint(int); +int ispunct(int); +int isspace(int); +int isupper(int); +int isxdigit(int); +int tolower(int); +int toupper(int); + +#ifndef __cplusplus +static __inline int __isspace(int _c) +{ + return _c == ' ' || (unsigned)_c-'\t' < 5; +} + +#define isalpha(a) (0 ? isalpha(a) : (((unsigned)(a)|32)-'a') < 26) +#define isdigit(a) (0 ? isdigit(a) : ((unsigned)(a)-'0') < 10) +#define islower(a) (0 ? islower(a) : ((unsigned)(a)-'a') < 26) +#define isupper(a) (0 ? isupper(a) : ((unsigned)(a)-'A') < 26) +#define isprint(a) (0 ? isprint(a) : ((unsigned)(a)-0x20) < 0x5f) +#define isgraph(a) (0 ? isgraph(a) : ((unsigned)(a)-0x21) < 0x5e) +#define isspace(a) __isspace(a) +#endif + + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) + +#define __NEED_locale_t +#include + +int isalnum_l(int, locale_t); +int isalpha_l(int, locale_t); +int isblank_l(int, locale_t); +int iscntrl_l(int, locale_t); +int isdigit_l(int, locale_t); +int isgraph_l(int, locale_t); +int islower_l(int, locale_t); +int isprint_l(int, locale_t); +int ispunct_l(int, locale_t); +int isspace_l(int, locale_t); +int isupper_l(int, locale_t); +int isxdigit_l(int, locale_t); +int tolower_l(int, locale_t); +int toupper_l(int, locale_t); + +int isascii(int); +int toascii(int); +#define _tolower(a) ((a)|0x20) +#define _toupper(a) ((a)&0x5f) +#define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/dirent.h b/c/common/test/includes/standard-library/dirent.h new file mode 100644 index 0000000000..650ecf646a --- /dev/null +++ b/c/common/test/includes/standard-library/dirent.h @@ -0,0 +1,75 @@ +#ifndef _DIRENT_H +#define _DIRENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_ino_t +#define __NEED_off_t +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define __NEED_size_t +#endif + +#include + +#include + +typedef struct __dirstream DIR; + +#define d_fileno d_ino + +int closedir(DIR *); +DIR *fdopendir(int); +DIR *opendir(const char *); +struct dirent *readdir(DIR *); +int readdir_r(DIR *__restrict, struct dirent *__restrict, struct dirent **__restrict); +void rewinddir(DIR *); +int dirfd(DIR *); + +int alphasort(const struct dirent **, const struct dirent **); +int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **)); + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +void seekdir(DIR *, long); +long telldir(DIR *); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 +#define IFTODT(x) ((x)>>12 & 017) +#define DTTOIF(x) ((x)<<12) +int getdents(int, struct dirent *, size_t); +#endif + +#ifdef _GNU_SOURCE +int versionsort(const struct dirent **, const struct dirent **); +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define dirent64 dirent +#define readdir64 readdir +#define readdir64_r readdir_r +#define scandir64 scandir +#define alphasort64 alphasort +#define versionsort64 versionsort +#define off64_t off_t +#define ino64_t ino_t +#define getdents64 getdents +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/dlfcn.h b/c/common/test/includes/standard-library/dlfcn.h new file mode 100644 index 0000000000..13ab71dd07 --- /dev/null +++ b/c/common/test/includes/standard-library/dlfcn.h @@ -0,0 +1,46 @@ +#ifndef _DLFCN_H +#define _DLFCN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define RTLD_LAZY 1 +#define RTLD_NOW 2 +#define RTLD_NOLOAD 4 +#define RTLD_NODELETE 4096 +#define RTLD_GLOBAL 256 +#define RTLD_LOCAL 0 + +#define RTLD_NEXT ((void *)-1) +#define RTLD_DEFAULT ((void *)0) + +#define RTLD_DI_LINKMAP 2 + +int dlclose(void *); +char *dlerror(void); +void *dlopen(const char *, int); +void *dlsym(void *__restrict, const char *__restrict); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef struct { + const char *dli_fname; + void *dli_fbase; + const char *dli_sname; + void *dli_saddr; +} Dl_info; +int dladdr(const void *, Dl_info *); +int dlinfo(void *, int, void *); +#endif + +#if _REDIR_TIME64 +__REDIR(dlsym, __dlsym_time64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/elf.h b/c/common/test/includes/standard-library/elf.h new file mode 100644 index 0000000000..b5e7befb02 --- /dev/null +++ b/c/common/test/includes/standard-library/elf.h @@ -0,0 +1,3294 @@ +#ifndef _ELF_H +#define _ELF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + +#define EI_NIDENT (16) + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +#define EI_MAG0 0 +#define ELFMAG0 0x7f + +#define EI_MAG1 1 +#define ELFMAG1 'E' + +#define EI_MAG2 2 +#define ELFMAG2 'L' + +#define EI_MAG3 3 +#define ELFMAG3 'F' + + +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define EI_DATA 5 +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 +#define ELFDATANUM 3 + +#define EI_VERSION 6 + + +#define EI_OSABI 7 +#define ELFOSABI_NONE 0 +#define ELFOSABI_SYSV 0 +#define ELFOSABI_HPUX 1 +#define ELFOSABI_NETBSD 2 +#define ELFOSABI_LINUX 3 +#define ELFOSABI_GNU 3 +#define ELFOSABI_SOLARIS 6 +#define ELFOSABI_AIX 7 +#define ELFOSABI_IRIX 8 +#define ELFOSABI_FREEBSD 9 +#define ELFOSABI_TRU64 10 +#define ELFOSABI_MODESTO 11 +#define ELFOSABI_OPENBSD 12 +#define ELFOSABI_ARM 97 +#define ELFOSABI_STANDALONE 255 + +#define EI_ABIVERSION 8 + +#define EI_PAD 9 + + + +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_NUM 5 +#define ET_LOOS 0xfe00 +#define ET_HIOS 0xfeff +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + + + +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_860 7 +#define EM_MIPS 8 +#define EM_S370 9 +#define EM_MIPS_RS3_LE 10 + +#define EM_PARISC 15 +#define EM_VPP500 17 +#define EM_SPARC32PLUS 18 +#define EM_960 19 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 + +#define EM_V800 36 +#define EM_FR20 37 +#define EM_RH32 38 +#define EM_RCE 39 +#define EM_ARM 40 +#define EM_FAKE_ALPHA 41 +#define EM_SH 42 +#define EM_SPARCV9 43 +#define EM_TRICORE 44 +#define EM_ARC 45 +#define EM_H8_300 46 +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_H8_500 49 +#define EM_IA_64 50 +#define EM_MIPS_X 51 +#define EM_COLDFIRE 52 +#define EM_68HC12 53 +#define EM_MMA 54 +#define EM_PCP 55 +#define EM_NCPU 56 +#define EM_NDR1 57 +#define EM_STARCORE 58 +#define EM_ME16 59 +#define EM_ST100 60 +#define EM_TINYJ 61 +#define EM_X86_64 62 +#define EM_PDSP 63 + +#define EM_FX66 66 +#define EM_ST9PLUS 67 +#define EM_ST7 68 +#define EM_68HC16 69 +#define EM_68HC11 70 +#define EM_68HC08 71 +#define EM_68HC05 72 +#define EM_SVX 73 +#define EM_ST19 74 +#define EM_VAX 75 +#define EM_CRIS 76 +#define EM_JAVELIN 77 +#define EM_FIREPATH 78 +#define EM_ZSP 79 +#define EM_MMIX 80 +#define EM_HUANY 81 +#define EM_PRISM 82 +#define EM_AVR 83 +#define EM_FR30 84 +#define EM_D10V 85 +#define EM_D30V 86 +#define EM_V850 87 +#define EM_M32R 88 +#define EM_MN10300 89 +#define EM_MN10200 90 +#define EM_PJ 91 +#define EM_OR1K 92 +#define EM_OPENRISC 92 +#define EM_ARC_A5 93 +#define EM_ARC_COMPACT 93 +#define EM_XTENSA 94 +#define EM_VIDEOCORE 95 +#define EM_TMM_GPP 96 +#define EM_NS32K 97 +#define EM_TPC 98 +#define EM_SNP1K 99 +#define EM_ST200 100 +#define EM_IP2K 101 +#define EM_MAX 102 +#define EM_CR 103 +#define EM_F2MC16 104 +#define EM_MSP430 105 +#define EM_BLACKFIN 106 +#define EM_SE_C33 107 +#define EM_SEP 108 +#define EM_ARCA 109 +#define EM_UNICORE 110 +#define EM_EXCESS 111 +#define EM_DXP 112 +#define EM_ALTERA_NIOS2 113 +#define EM_CRX 114 +#define EM_XGATE 115 +#define EM_C166 116 +#define EM_M16C 117 +#define EM_DSPIC30F 118 +#define EM_CE 119 +#define EM_M32C 120 +#define EM_TSK3000 131 +#define EM_RS08 132 +#define EM_SHARC 133 +#define EM_ECOG2 134 +#define EM_SCORE7 135 +#define EM_DSP24 136 +#define EM_VIDEOCORE3 137 +#define EM_LATTICEMICO32 138 +#define EM_SE_C17 139 +#define EM_TI_C6000 140 +#define EM_TI_C2000 141 +#define EM_TI_C5500 142 +#define EM_TI_ARP32 143 +#define EM_TI_PRU 144 +#define EM_MMDSP_PLUS 160 +#define EM_CYPRESS_M8C 161 +#define EM_R32C 162 +#define EM_TRIMEDIA 163 +#define EM_QDSP6 164 +#define EM_8051 165 +#define EM_STXP7X 166 +#define EM_NDS32 167 +#define EM_ECOG1X 168 +#define EM_MAXQ30 169 +#define EM_XIMO16 170 +#define EM_MANIK 171 +#define EM_CRAYNV2 172 +#define EM_RX 173 +#define EM_METAG 174 +#define EM_MCST_ELBRUS 175 +#define EM_ECOG16 176 +#define EM_CR16 177 +#define EM_ETPU 178 +#define EM_SLE9X 179 +#define EM_L10M 180 +#define EM_K10M 181 +#define EM_AARCH64 183 +#define EM_AVR32 185 +#define EM_STM8 186 +#define EM_TILE64 187 +#define EM_TILEPRO 188 +#define EM_MICROBLAZE 189 +#define EM_CUDA 190 +#define EM_TILEGX 191 +#define EM_CLOUDSHIELD 192 +#define EM_COREA_1ST 193 +#define EM_COREA_2ND 194 +#define EM_ARC_COMPACT2 195 +#define EM_OPEN8 196 +#define EM_RL78 197 +#define EM_VIDEOCORE5 198 +#define EM_78KOR 199 +#define EM_56800EX 200 +#define EM_BA1 201 +#define EM_BA2 202 +#define EM_XCORE 203 +#define EM_MCHP_PIC 204 +#define EM_KM32 210 +#define EM_KMX32 211 +#define EM_EMX16 212 +#define EM_EMX8 213 +#define EM_KVARC 214 +#define EM_CDP 215 +#define EM_COGE 216 +#define EM_COOL 217 +#define EM_NORC 218 +#define EM_CSR_KALIMBA 219 +#define EM_Z80 220 +#define EM_VISIUM 221 +#define EM_FT32 222 +#define EM_MOXIE 223 +#define EM_AMDGPU 224 +#define EM_RISCV 243 +#define EM_BPF 247 +#define EM_CSKY 252 +#define EM_NUM 253 + +#define EM_ALPHA 0x9026 + +#define EV_NONE 0 +#define EV_CURRENT 1 +#define EV_NUM 2 + +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + + + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_BEFORE 0xff00 + +#define SHN_AFTER 0xff01 + +#define SHN_HIPROC 0xff1f +#define SHN_LOOS 0xff20 +#define SHN_HIOS 0xff3f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_XINDEX 0xffff +#define SHN_HIRESERVE 0xffff + + + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 +#define SHT_NUM 19 +#define SHT_LOOS 0x60000000 +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_CHECKSUM 0x6ffffff8 +#define SHT_LOSUNW 0x6ffffffa +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd +#define SHT_GNU_verneed 0x6ffffffe +#define SHT_GNU_versym 0x6fffffff +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0x8fffffff + +#define SHF_WRITE (1 << 0) +#define SHF_ALLOC (1 << 1) +#define SHF_EXECINSTR (1 << 2) +#define SHF_MERGE (1 << 4) +#define SHF_STRINGS (1 << 5) +#define SHF_INFO_LINK (1 << 6) +#define SHF_LINK_ORDER (1 << 7) +#define SHF_OS_NONCONFORMING (1 << 8) + +#define SHF_GROUP (1 << 9) +#define SHF_TLS (1 << 10) +#define SHF_COMPRESSED (1 << 11) +#define SHF_MASKOS 0x0ff00000 +#define SHF_MASKPROC 0xf0000000 +#define SHF_ORDERED (1 << 30) +#define SHF_EXCLUDE (1U << 31) + +typedef struct { + Elf32_Word ch_type; + Elf32_Word ch_size; + Elf32_Word ch_addralign; +} Elf32_Chdr; + +typedef struct { + Elf64_Word ch_type; + Elf64_Word ch_reserved; + Elf64_Xword ch_size; + Elf64_Xword ch_addralign; +} Elf64_Chdr; + +#define ELFCOMPRESS_ZLIB 1 +#define ELFCOMPRESS_LOOS 0x60000000 +#define ELFCOMPRESS_HIOS 0x6fffffff +#define ELFCOMPRESS_LOPROC 0x70000000 +#define ELFCOMPRESS_HIPROC 0x7fffffff + + +#define GRP_COMDAT 0x1 + +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Section st_shndx; +} Elf32_Sym; + +typedef struct { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Section st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +typedef struct { + Elf32_Half si_boundto; + Elf32_Half si_flags; +} Elf32_Syminfo; + +typedef struct { + Elf64_Half si_boundto; + Elf64_Half si_flags; +} Elf64_Syminfo; + +#define SYMINFO_BT_SELF 0xffff +#define SYMINFO_BT_PARENT 0xfffe +#define SYMINFO_BT_LOWRESERVE 0xff00 + +#define SYMINFO_FLG_DIRECT 0x0001 +#define SYMINFO_FLG_PASSTHRU 0x0002 +#define SYMINFO_FLG_COPY 0x0004 +#define SYMINFO_FLG_LAZYLOAD 0x0008 + +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_NUM 3 +#define STB_LOOS 10 +#define STB_GNU_UNIQUE 10 +#define STB_HIOS 12 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 +#define STT_NUM 7 +#define STT_LOOS 10 +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + +#define STN_UNDEF 0 + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +#define STV_DEFAULT 0 +#define STV_INTERNAL 1 +#define STV_HIDDEN 2 +#define STV_PROTECTED 3 + + + + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + + + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + + + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + + + +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + + + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 +#define PT_NUM 8 +#define PT_LOOS 0x60000000 +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_GNU_PROPERTY 0x6474e553 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa +#define PT_SUNWSTACK 0x6ffffffb +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + + +#define PN_XNUM 0xffff + + +#define PF_X (1 << 0) +#define PF_W (1 << 1) +#define PF_R (1 << 2) +#define PF_MASKOS 0x0ff00000 +#define PF_MASKPROC 0xf0000000 + + + +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_FPREGSET 2 +#define NT_PRPSINFO 3 +#define NT_PRXREG 4 +#define NT_TASKSTRUCT 4 +#define NT_PLATFORM 5 +#define NT_AUXV 6 +#define NT_GWINDOWS 7 +#define NT_ASRS 8 +#define NT_PSTATUS 10 +#define NT_PSINFO 13 +#define NT_PRCRED 14 +#define NT_UTSNAME 15 +#define NT_LWPSTATUS 16 +#define NT_LWPSINFO 17 +#define NT_PRFPXREG 20 +#define NT_SIGINFO 0x53494749 +#define NT_FILE 0x46494c45 +#define NT_PRXFPREG 0x46e62b7f +#define NT_PPC_VMX 0x100 +#define NT_PPC_SPE 0x101 +#define NT_PPC_VSX 0x102 +#define NT_PPC_TAR 0x103 +#define NT_PPC_PPR 0x104 +#define NT_PPC_DSCR 0x105 +#define NT_PPC_EBB 0x106 +#define NT_PPC_PMU 0x107 +#define NT_PPC_TM_CGPR 0x108 +#define NT_PPC_TM_CFPR 0x109 +#define NT_PPC_TM_CVMX 0x10a +#define NT_PPC_TM_CVSX 0x10b +#define NT_PPC_TM_SPR 0x10c +#define NT_PPC_TM_CTAR 0x10d +#define NT_PPC_TM_CPPR 0x10e +#define NT_PPC_TM_CDSCR 0x10f +#define NT_386_TLS 0x200 +#define NT_386_IOPERM 0x201 +#define NT_X86_XSTATE 0x202 +#define NT_S390_HIGH_GPRS 0x300 +#define NT_S390_TIMER 0x301 +#define NT_S390_TODCMP 0x302 +#define NT_S390_TODPREG 0x303 +#define NT_S390_CTRS 0x304 +#define NT_S390_PREFIX 0x305 +#define NT_S390_LAST_BREAK 0x306 +#define NT_S390_SYSTEM_CALL 0x307 +#define NT_S390_TDB 0x308 +#define NT_S390_VXRS_LOW 0x309 +#define NT_S390_VXRS_HIGH 0x30a +#define NT_S390_GS_CB 0x30b +#define NT_S390_GS_BC 0x30c +#define NT_S390_RI_CB 0x30d +#define NT_ARM_VFP 0x400 +#define NT_ARM_TLS 0x401 +#define NT_ARM_HW_BREAK 0x402 +#define NT_ARM_HW_WATCH 0x403 +#define NT_ARM_SYSTEM_CALL 0x404 +#define NT_ARM_SVE 0x405 +#define NT_ARM_PAC_MASK 0x406 +#define NT_ARM_PACA_KEYS 0x407 +#define NT_ARM_PACG_KEYS 0x408 +#define NT_METAG_CBUF 0x500 +#define NT_METAG_RPIPE 0x501 +#define NT_METAG_TLS 0x502 +#define NT_ARC_V2 0x600 +#define NT_VMCOREDD 0x700 +#define NT_MIPS_DSP 0x800 +#define NT_MIPS_FP_MODE 0x801 +#define NT_MIPS_MSA 0x802 +#define NT_VERSION 1 + + + + +typedef struct { + Elf32_Sword d_tag; + union { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + + + +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_BIND_NOW 24 +#define DT_INIT_ARRAY 25 +#define DT_FINI_ARRAY 26 +#define DT_INIT_ARRAYSZ 27 +#define DT_FINI_ARRAYSZ 28 +#define DT_RUNPATH 29 +#define DT_FLAGS 30 +#define DT_ENCODING 32 +#define DT_PREINIT_ARRAY 32 +#define DT_PREINIT_ARRAYSZ 33 +#define DT_SYMTAB_SHNDX 34 +#define DT_NUM 35 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff +#define DT_PROCNUM DT_MIPS_NUM + +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc +#define DT_POSFLAG_1 0x6ffffdfd + +#define DT_SYMINSZ 0x6ffffdfe +#define DT_SYMINENT 0x6ffffdff +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) +#define DT_VALNUM 12 + +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 +#define DT_TLSDESC_PLT 0x6ffffef6 +#define DT_TLSDESC_GOT 0x6ffffef7 +#define DT_GNU_CONFLICT 0x6ffffef8 +#define DT_GNU_LIBLIST 0x6ffffef9 +#define DT_CONFIG 0x6ffffefa +#define DT_DEPAUDIT 0x6ffffefb +#define DT_AUDIT 0x6ffffefc +#define DT_PLTPAD 0x6ffffefd +#define DT_MOVETAB 0x6ffffefe +#define DT_SYMINFO 0x6ffffeff +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) +#define DT_ADDRNUM 11 + + + +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + + +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc + +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe + +#define DT_VERNEEDNUM 0x6fffffff +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) +#define DT_VERSIONTAGNUM 16 + + + +#define DT_AUXILIARY 0x7ffffffd +#define DT_FILTER 0x7fffffff +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + + +#define DF_ORIGIN 0x00000001 +#define DF_SYMBOLIC 0x00000002 +#define DF_TEXTREL 0x00000004 +#define DF_BIND_NOW 0x00000008 +#define DF_STATIC_TLS 0x00000010 + + + +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONFALT 0x00002000 +#define DF_1_ENDFILTEE 0x00004000 +#define DF_1_DISPRELDNE 0x00008000 +#define DF_1_DISPRELPND 0x00010000 +#define DF_1_NODIRECT 0x00020000 +#define DF_1_IGNMULDEF 0x00040000 +#define DF_1_NOKSYMS 0x00080000 +#define DF_1_NOHDR 0x00100000 +#define DF_1_EDITED 0x00200000 +#define DF_1_NORELOC 0x00400000 +#define DF_1_SYMINTPOSE 0x00800000 +#define DF_1_GLOBAUDIT 0x01000000 +#define DF_1_SINGLETON 0x02000000 +#define DF_1_STUB 0x04000000 +#define DF_1_PIE 0x08000000 + +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + + +#define DF_P1_LAZYLOAD 0x00000001 +#define DF_P1_GROUPPERM 0x00000002 + + + + +typedef struct { + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + + + +#define VER_DEF_NONE 0 +#define VER_DEF_CURRENT 1 +#define VER_DEF_NUM 2 + + +#define VER_FLG_BASE 0x1 +#define VER_FLG_WEAK 0x2 + + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_LORESERVE 0xff00 +#define VER_NDX_ELIMINATE 0xff01 + + + +typedef struct { + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + + + + +typedef struct { + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + + + +#define VER_NEED_NONE 0 +#define VER_NEED_CURRENT 1 +#define VER_NEED_NUM 2 + + + +typedef struct { + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + + + +#define VER_FLG_WEAK 0x2 + + + +typedef struct { + uint32_t a_type; + union { + uint32_t a_val; + } a_un; +} Elf32_auxv_t; + +typedef struct { + uint64_t a_type; + union { + uint64_t a_val; + } a_un; +} Elf64_auxv_t; + + + +#define AT_NULL 0 +#define AT_IGNORE 1 +#define AT_EXECFD 2 +#define AT_PHDR 3 +#define AT_PHENT 4 +#define AT_PHNUM 5 +#define AT_PAGESZ 6 +#define AT_BASE 7 +#define AT_FLAGS 8 +#define AT_ENTRY 9 +#define AT_NOTELF 10 +#define AT_UID 11 +#define AT_EUID 12 +#define AT_GID 13 +#define AT_EGID 14 +#define AT_CLKTCK 17 + + +#define AT_PLATFORM 15 +#define AT_HWCAP 16 + + + + +#define AT_FPUCW 18 + + +#define AT_DCACHEBSIZE 19 +#define AT_ICACHEBSIZE 20 +#define AT_UCACHEBSIZE 21 + + + +#define AT_IGNOREPPC 22 + +#define AT_SECURE 23 + +#define AT_BASE_PLATFORM 24 + +#define AT_RANDOM 25 + +#define AT_HWCAP2 26 + +#define AT_EXECFN 31 + + + +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + + + +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +#define AT_L1I_CACHESIZE 40 +#define AT_L1I_CACHEGEOMETRY 41 +#define AT_L1D_CACHESIZE 42 +#define AT_L1D_CACHEGEOMETRY 43 +#define AT_L2_CACHESIZE 44 +#define AT_L2_CACHEGEOMETRY 45 +#define AT_L3_CACHESIZE 46 +#define AT_L3_CACHEGEOMETRY 47 + +#define AT_MINSIGSTKSZ 51 + + +typedef struct { + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +} Elf32_Nhdr; + +typedef struct { + Elf64_Word n_namesz; + Elf64_Word n_descsz; + Elf64_Word n_type; +} Elf64_Nhdr; + + + + +#define ELF_NOTE_SOLARIS "SUNW Solaris" + + +#define ELF_NOTE_GNU "GNU" + + + + + +#define ELF_NOTE_PAGESIZE_HINT 1 + + +#define NT_GNU_ABI_TAG 1 +#define ELF_NOTE_ABI NT_GNU_ABI_TAG + + + +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + +#define NT_GNU_BUILD_ID 3 +#define NT_GNU_GOLD_VERSION 4 +#define NT_GNU_PROPERTY_TYPE_0 5 + + + +typedef struct { + Elf32_Xword m_value; + Elf32_Word m_info; + Elf32_Word m_poffset; + Elf32_Half m_repeat; + Elf32_Half m_stride; +} Elf32_Move; + +typedef struct { + Elf64_Xword m_value; + Elf64_Xword m_info; + Elf64_Xword m_poffset; + Elf64_Half m_repeat; + Elf64_Half m_stride; +} Elf64_Move; + + +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + +#define EF_CPU32 0x00810000 + +#define R_68K_NONE 0 +#define R_68K_32 1 +#define R_68K_16 2 +#define R_68K_8 3 +#define R_68K_PC32 4 +#define R_68K_PC16 5 +#define R_68K_PC8 6 +#define R_68K_GOT32 7 +#define R_68K_GOT16 8 +#define R_68K_GOT8 9 +#define R_68K_GOT32O 10 +#define R_68K_GOT16O 11 +#define R_68K_GOT8O 12 +#define R_68K_PLT32 13 +#define R_68K_PLT16 14 +#define R_68K_PLT8 15 +#define R_68K_PLT32O 16 +#define R_68K_PLT16O 17 +#define R_68K_PLT8O 18 +#define R_68K_COPY 19 +#define R_68K_GLOB_DAT 20 +#define R_68K_JMP_SLOT 21 +#define R_68K_RELATIVE 22 +#define R_68K_TLS_GD32 25 +#define R_68K_TLS_GD16 26 +#define R_68K_TLS_GD8 27 +#define R_68K_TLS_LDM32 28 +#define R_68K_TLS_LDM16 29 +#define R_68K_TLS_LDM8 30 +#define R_68K_TLS_LDO32 31 +#define R_68K_TLS_LDO16 32 +#define R_68K_TLS_LDO8 33 +#define R_68K_TLS_IE32 34 +#define R_68K_TLS_IE16 35 +#define R_68K_TLS_IE8 36 +#define R_68K_TLS_LE32 37 +#define R_68K_TLS_LE16 38 +#define R_68K_TLS_LE8 39 +#define R_68K_TLS_DTPMOD32 40 +#define R_68K_TLS_DTPREL32 41 +#define R_68K_TLS_TPREL32 42 +#define R_68K_NUM 43 + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 +#define R_386_TLS_IE 15 +#define R_386_TLS_GOTIE 16 +#define R_386_TLS_LE 17 +#define R_386_TLS_GD 18 +#define R_386_TLS_LDM 19 +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 +#define R_386_TLS_GD_PUSH 25 +#define R_386_TLS_GD_CALL 26 +#define R_386_TLS_GD_POP 27 +#define R_386_TLS_LDM_32 28 +#define R_386_TLS_LDM_PUSH 29 +#define R_386_TLS_LDM_CALL 30 +#define R_386_TLS_LDM_POP 31 +#define R_386_TLS_LDO_32 32 +#define R_386_TLS_IE_32 33 +#define R_386_TLS_LE_32 34 +#define R_386_TLS_DTPMOD32 35 +#define R_386_TLS_DTPOFF32 36 +#define R_386_TLS_TPOFF32 37 +#define R_386_SIZE32 38 +#define R_386_TLS_GOTDESC 39 +#define R_386_TLS_DESC_CALL 40 +#define R_386_TLS_DESC 41 +#define R_386_IRELATIVE 42 +#define R_386_GOT32X 43 +#define R_386_NUM 44 + + + + + +#define STT_SPARC_REGISTER 13 + + + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 +#define EF_SPARC_SUN_US1 0x000200 +#define EF_SPARC_HAL_R1 0x000400 +#define EF_SPARC_SUN_US3 0x000800 + + + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 + + + +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 +#define R_SPARC_GOTDATA_HIX22 80 +#define R_SPARC_GOTDATA_LOX10 81 +#define R_SPARC_GOTDATA_OP_HIX22 82 +#define R_SPARC_GOTDATA_OP_LOX10 83 +#define R_SPARC_GOTDATA_OP 84 +#define R_SPARC_H34 85 +#define R_SPARC_SIZE32 86 +#define R_SPARC_SIZE64 87 +#define R_SPARC_GNU_VTINHERIT 250 +#define R_SPARC_GNU_VTENTRY 251 +#define R_SPARC_REV32 252 + +#define R_SPARC_NUM 253 + + + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + + +#define EF_MIPS_NOREORDER 1 +#define EF_MIPS_PIC 2 +#define EF_MIPS_CPIC 4 +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_FP64 512 +#define EF_MIPS_NAN2008 1024 +#define EF_MIPS_ARCH 0xf0000000 + + + +#define EF_MIPS_ARCH_1 0x00000000 +#define EF_MIPS_ARCH_2 0x10000000 +#define EF_MIPS_ARCH_3 0x20000000 +#define EF_MIPS_ARCH_4 0x30000000 +#define EF_MIPS_ARCH_5 0x40000000 +#define EF_MIPS_ARCH_32 0x50000000 +#define EF_MIPS_ARCH_64 0x60000000 +#define EF_MIPS_ARCH_32R2 0x70000000 +#define EF_MIPS_ARCH_64R2 0x80000000 + + +#define E_MIPS_ARCH_1 0x00000000 +#define E_MIPS_ARCH_2 0x10000000 +#define E_MIPS_ARCH_3 0x20000000 +#define E_MIPS_ARCH_4 0x30000000 +#define E_MIPS_ARCH_5 0x40000000 +#define E_MIPS_ARCH_32 0x50000000 +#define E_MIPS_ARCH_64 0x60000000 + + + +#define SHN_MIPS_ACOMMON 0xff00 +#define SHN_MIPS_TEXT 0xff01 +#define SHN_MIPS_DATA 0xff02 +#define SHN_MIPS_SCOMMON 0xff03 +#define SHN_MIPS_SUNDEFINED 0xff04 + + + +#define SHT_MIPS_LIBLIST 0x70000000 +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 +#define SHT_MIPS_GPTAB 0x70000003 +#define SHT_MIPS_UCODE 0x70000004 +#define SHT_MIPS_DEBUG 0x70000005 +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + + + +#define SHF_MIPS_GPREL 0x10000000 +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + + + + + +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_PLT 0x8 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + + +#define STB_MIPS_SPLIT_COMMON 13 + + + +typedef union { + struct { + Elf32_Word gt_current_g_value; + Elf32_Word gt_unused; + } gt_header; + struct { + Elf32_Word gt_g_value; + Elf32_Word gt_bytes; + } gt_entry; +} Elf32_gptab; + + + +typedef struct { + Elf32_Word ri_gprmask; + Elf32_Word ri_cprmask[4]; + Elf32_Sword ri_gp_value; +} Elf32_RegInfo; + + + +typedef struct { + unsigned char kind; + + unsigned char size; + Elf32_Section section; + + Elf32_Word info; +} Elf_Options; + + + +#define ODK_NULL 0 +#define ODK_REGINFO 1 +#define ODK_EXCEPTIONS 2 +#define ODK_PAD 3 +#define ODK_HWPATCH 4 +#define ODK_FILL 5 +#define ODK_TAGS 6 +#define ODK_HWAND 7 +#define ODK_HWOR 8 + + + +#define OEX_FPU_MIN 0x1f +#define OEX_FPU_MAX 0x1f00 +#define OEX_PAGE0 0x10000 +#define OEX_SMM 0x20000 +#define OEX_FPDBUG 0x40000 +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + + + +#define OHW_R4KEOP 0x1 +#define OHW_R8KPFETCH 0x2 +#define OHW_R5KEOP 0x4 +#define OHW_R5KCVTL 0x8 + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + + + +typedef struct { + Elf32_Word hwp_flags1; + Elf32_Word hwp_flags2; +} Elf_Options_Hw; + + + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + + + +#define R_MIPS_NONE 0 +#define R_MIPS_16 1 +#define R_MIPS_32 2 +#define R_MIPS_REL32 3 +#define R_MIPS_26 4 +#define R_MIPS_HI16 5 +#define R_MIPS_LO16 6 +#define R_MIPS_GPREL16 7 +#define R_MIPS_LITERAL 8 +#define R_MIPS_GOT16 9 +#define R_MIPS_PC16 10 +#define R_MIPS_CALL16 11 +#define R_MIPS_GPREL32 12 + +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +#define R_MIPS_TLS_DTPMOD32 38 +#define R_MIPS_TLS_DTPREL32 39 +#define R_MIPS_TLS_DTPMOD64 40 +#define R_MIPS_TLS_DTPREL64 41 +#define R_MIPS_TLS_GD 42 +#define R_MIPS_TLS_LDM 43 +#define R_MIPS_TLS_DTPREL_HI16 44 +#define R_MIPS_TLS_DTPREL_LO16 45 +#define R_MIPS_TLS_GOTTPREL 46 +#define R_MIPS_TLS_TPREL32 47 +#define R_MIPS_TLS_TPREL64 48 +#define R_MIPS_TLS_TPREL_HI16 49 +#define R_MIPS_TLS_TPREL_LO16 50 +#define R_MIPS_GLOB_DAT 51 +#define R_MIPS_COPY 126 +#define R_MIPS_JUMP_SLOT 127 + +#define R_MIPS_NUM 128 + + + +#define PT_MIPS_REGINFO 0x70000000 +#define PT_MIPS_RTPROC 0x70000001 +#define PT_MIPS_OPTIONS 0x70000002 +#define PT_MIPS_ABIFLAGS 0x70000003 + + + +#define PF_MIPS_LOCAL 0x10000000 + + + +#define DT_MIPS_RLD_VERSION 0x70000001 +#define DT_MIPS_TIME_STAMP 0x70000002 +#define DT_MIPS_ICHECKSUM 0x70000003 +#define DT_MIPS_IVERSION 0x70000004 +#define DT_MIPS_FLAGS 0x70000005 +#define DT_MIPS_BASE_ADDRESS 0x70000006 +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 +#define DT_MIPS_LIBLIST 0x70000009 +#define DT_MIPS_LOCAL_GOTNO 0x7000000a +#define DT_MIPS_CONFLICTNO 0x7000000b +#define DT_MIPS_LIBLISTNO 0x70000010 +#define DT_MIPS_SYMTABNO 0x70000011 +#define DT_MIPS_UNREFEXTNO 0x70000012 +#define DT_MIPS_GOTSYM 0x70000013 +#define DT_MIPS_HIPAGENO 0x70000014 +#define DT_MIPS_RLD_MAP 0x70000016 +#define DT_MIPS_DELTA_CLASS 0x70000017 +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 + +#define DT_MIPS_DELTA_INSTANCE 0x70000019 +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a + +#define DT_MIPS_DELTA_RELOC 0x7000001b +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c + +#define DT_MIPS_DELTA_SYM 0x7000001d + +#define DT_MIPS_DELTA_SYM_NO 0x7000001e + +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 + +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 + +#define DT_MIPS_CXX_FLAGS 0x70000022 +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 +#define DT_MIPS_INTERFACE 0x7000002a +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d + +#define DT_MIPS_PERF_SUFFIX 0x7000002e + +#define DT_MIPS_COMPACT_SIZE 0x7000002f +#define DT_MIPS_GP_VALUE 0x70000030 +#define DT_MIPS_AUX_DYNAMIC 0x70000031 + +#define DT_MIPS_PLTGOT 0x70000032 + +#define DT_MIPS_RWPLT 0x70000034 +#define DT_MIPS_RLD_MAP_REL 0x70000035 +#define DT_MIPS_NUM 0x36 + + + +#define RHF_NONE 0 +#define RHF_QUICKSTART (1 << 0) +#define RHF_NOTPOT (1 << 1) +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + + + +typedef struct { + Elf32_Word l_name; + Elf32_Word l_time_stamp; + Elf32_Word l_checksum; + Elf32_Word l_version; + Elf32_Word l_flags; +} Elf32_Lib; + +typedef struct { + Elf64_Word l_name; + Elf64_Word l_time_stamp; + Elf64_Word l_checksum; + Elf64_Word l_version; + Elf64_Word l_flags; +} Elf64_Lib; + + + + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) +#define LL_IGNORE_INT_VER (1 << 1) +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + + + +typedef Elf32_Addr Elf32_Conflict; + +typedef struct { + Elf32_Half version; + unsigned char isa_level; + unsigned char isa_rev; + unsigned char gpr_size; + unsigned char cpr1_size; + unsigned char cpr2_size; + unsigned char fp_abi; + Elf32_Word isa_ext; + Elf32_Word ases; + Elf32_Word flags1; + Elf32_Word flags2; +} Elf_MIPS_ABIFlags_v0; + +#define MIPS_AFL_REG_NONE 0x00 +#define MIPS_AFL_REG_32 0x01 +#define MIPS_AFL_REG_64 0x02 +#define MIPS_AFL_REG_128 0x03 + +#define MIPS_AFL_ASE_DSP 0x00000001 +#define MIPS_AFL_ASE_DSPR2 0x00000002 +#define MIPS_AFL_ASE_EVA 0x00000004 +#define MIPS_AFL_ASE_MCU 0x00000008 +#define MIPS_AFL_ASE_MDMX 0x00000010 +#define MIPS_AFL_ASE_MIPS3D 0x00000020 +#define MIPS_AFL_ASE_MT 0x00000040 +#define MIPS_AFL_ASE_SMARTMIPS 0x00000080 +#define MIPS_AFL_ASE_VIRT 0x00000100 +#define MIPS_AFL_ASE_MSA 0x00000200 +#define MIPS_AFL_ASE_MIPS16 0x00000400 +#define MIPS_AFL_ASE_MICROMIPS 0x00000800 +#define MIPS_AFL_ASE_XPA 0x00001000 +#define MIPS_AFL_ASE_MASK 0x00001fff + +#define MIPS_AFL_EXT_XLR 1 +#define MIPS_AFL_EXT_OCTEON2 2 +#define MIPS_AFL_EXT_OCTEONP 3 +#define MIPS_AFL_EXT_LOONGSON_3A 4 +#define MIPS_AFL_EXT_OCTEON 5 +#define MIPS_AFL_EXT_5900 6 +#define MIPS_AFL_EXT_4650 7 +#define MIPS_AFL_EXT_4010 8 +#define MIPS_AFL_EXT_4100 9 +#define MIPS_AFL_EXT_3900 10 +#define MIPS_AFL_EXT_10000 11 +#define MIPS_AFL_EXT_SB1 12 +#define MIPS_AFL_EXT_4111 13 +#define MIPS_AFL_EXT_4120 14 +#define MIPS_AFL_EXT_5400 15 +#define MIPS_AFL_EXT_5500 16 +#define MIPS_AFL_EXT_LOONGSON_2E 17 +#define MIPS_AFL_EXT_LOONGSON_2F 18 + +#define MIPS_AFL_FLAGS1_ODDSPREG 1 + +enum +{ + Val_GNU_MIPS_ABI_FP_ANY = 0, + Val_GNU_MIPS_ABI_FP_DOUBLE = 1, + Val_GNU_MIPS_ABI_FP_SINGLE = 2, + Val_GNU_MIPS_ABI_FP_SOFT = 3, + Val_GNU_MIPS_ABI_FP_OLD_64 = 4, + Val_GNU_MIPS_ABI_FP_XX = 5, + Val_GNU_MIPS_ABI_FP_64 = 6, + Val_GNU_MIPS_ABI_FP_64A = 7, + Val_GNU_MIPS_ABI_FP_MAX = 7 +}; + + + + +#define EF_PARISC_TRAPNIL 0x00010000 +#define EF_PARISC_EXT 0x00020000 +#define EF_PARISC_LSB 0x00040000 +#define EF_PARISC_WIDE 0x00080000 +#define EF_PARISC_NO_KABP 0x00100000 + +#define EF_PARISC_LAZYSWAP 0x00400000 +#define EF_PARISC_ARCH 0x0000ffff + + + +#define EFA_PARISC_1_0 0x020b +#define EFA_PARISC_1_1 0x0210 +#define EFA_PARISC_2_0 0x0214 + + + +#define SHN_PARISC_ANSI_COMMON 0xff00 + +#define SHN_PARISC_HUGE_COMMON 0xff01 + + + +#define SHT_PARISC_EXT 0x70000000 +#define SHT_PARISC_UNWIND 0x70000001 +#define SHT_PARISC_DOC 0x70000002 + + + +#define SHF_PARISC_SHORT 0x20000000 +#define SHF_PARISC_HUGE 0x40000000 +#define SHF_PARISC_SBP 0x80000000 + + + +#define STT_PARISC_MILLICODE 13 + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + + + +#define R_PARISC_NONE 0 +#define R_PARISC_DIR32 1 +#define R_PARISC_DIR21L 2 +#define R_PARISC_DIR17R 3 +#define R_PARISC_DIR17F 4 +#define R_PARISC_DIR14R 6 +#define R_PARISC_PCREL32 9 +#define R_PARISC_PCREL21L 10 +#define R_PARISC_PCREL17R 11 +#define R_PARISC_PCREL17F 12 +#define R_PARISC_PCREL14R 14 +#define R_PARISC_DPREL21L 18 +#define R_PARISC_DPREL14R 22 +#define R_PARISC_GPREL21L 26 +#define R_PARISC_GPREL14R 30 +#define R_PARISC_LTOFF21L 34 +#define R_PARISC_LTOFF14R 38 +#define R_PARISC_SECREL32 41 +#define R_PARISC_SEGBASE 48 +#define R_PARISC_SEGREL32 49 +#define R_PARISC_PLTOFF21L 50 +#define R_PARISC_PLTOFF14R 54 +#define R_PARISC_LTOFF_FPTR32 57 +#define R_PARISC_LTOFF_FPTR21L 58 +#define R_PARISC_LTOFF_FPTR14R 62 +#define R_PARISC_FPTR64 64 +#define R_PARISC_PLABEL32 65 +#define R_PARISC_PLABEL21L 66 +#define R_PARISC_PLABEL14R 70 +#define R_PARISC_PCREL64 72 +#define R_PARISC_PCREL22F 74 +#define R_PARISC_PCREL14WR 75 +#define R_PARISC_PCREL14DR 76 +#define R_PARISC_PCREL16F 77 +#define R_PARISC_PCREL16WF 78 +#define R_PARISC_PCREL16DF 79 +#define R_PARISC_DIR64 80 +#define R_PARISC_DIR14WR 83 +#define R_PARISC_DIR14DR 84 +#define R_PARISC_DIR16F 85 +#define R_PARISC_DIR16WF 86 +#define R_PARISC_DIR16DF 87 +#define R_PARISC_GPREL64 88 +#define R_PARISC_GPREL14WR 91 +#define R_PARISC_GPREL14DR 92 +#define R_PARISC_GPREL16F 93 +#define R_PARISC_GPREL16WF 94 +#define R_PARISC_GPREL16DF 95 +#define R_PARISC_LTOFF64 96 +#define R_PARISC_LTOFF14WR 99 +#define R_PARISC_LTOFF14DR 100 +#define R_PARISC_LTOFF16F 101 +#define R_PARISC_LTOFF16WF 102 +#define R_PARISC_LTOFF16DF 103 +#define R_PARISC_SECREL64 104 +#define R_PARISC_SEGREL64 112 +#define R_PARISC_PLTOFF14WR 115 +#define R_PARISC_PLTOFF14DR 116 +#define R_PARISC_PLTOFF16F 117 +#define R_PARISC_PLTOFF16WF 118 +#define R_PARISC_PLTOFF16DF 119 +#define R_PARISC_LTOFF_FPTR64 120 +#define R_PARISC_LTOFF_FPTR14WR 123 +#define R_PARISC_LTOFF_FPTR14DR 124 +#define R_PARISC_LTOFF_FPTR16F 125 +#define R_PARISC_LTOFF_FPTR16WF 126 +#define R_PARISC_LTOFF_FPTR16DF 127 +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 +#define R_PARISC_IPLT 129 +#define R_PARISC_EPLT 130 +#define R_PARISC_TPREL32 153 +#define R_PARISC_TPREL21L 154 +#define R_PARISC_TPREL14R 158 +#define R_PARISC_LTOFF_TP21L 162 +#define R_PARISC_LTOFF_TP14R 166 +#define R_PARISC_LTOFF_TP14F 167 +#define R_PARISC_TPREL64 216 +#define R_PARISC_TPREL14WR 219 +#define R_PARISC_TPREL14DR 220 +#define R_PARISC_TPREL16F 221 +#define R_PARISC_TPREL16WF 222 +#define R_PARISC_TPREL16DF 223 +#define R_PARISC_LTOFF_TP64 224 +#define R_PARISC_LTOFF_TP14WR 227 +#define R_PARISC_LTOFF_TP14DR 228 +#define R_PARISC_LTOFF_TP16F 229 +#define R_PARISC_LTOFF_TP16WF 230 +#define R_PARISC_LTOFF_TP16DF 231 +#define R_PARISC_GNU_VTENTRY 232 +#define R_PARISC_GNU_VTINHERIT 233 +#define R_PARISC_TLS_GD21L 234 +#define R_PARISC_TLS_GD14R 235 +#define R_PARISC_TLS_GDCALL 236 +#define R_PARISC_TLS_LDM21L 237 +#define R_PARISC_TLS_LDM14R 238 +#define R_PARISC_TLS_LDMCALL 239 +#define R_PARISC_TLS_LDO21L 240 +#define R_PARISC_TLS_LDO14R 241 +#define R_PARISC_TLS_DTPMOD32 242 +#define R_PARISC_TLS_DTPMOD64 243 +#define R_PARISC_TLS_DTPOFF32 244 +#define R_PARISC_TLS_DTPOFF64 245 +#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L +#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R +#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L +#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R +#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32 +#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64 +#define R_PARISC_HIRESERVE 255 + + + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + + + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + + + + + + +#define EF_ALPHA_32BIT 1 +#define EF_ALPHA_CANRELAX 2 + + + + +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + + + +#define SHF_ALPHA_GPREL 0x10000000 + + +#define STO_ALPHA_NOPV 0x80 +#define STO_ALPHA_STD_GPLOAD 0x88 + + + +#define R_ALPHA_NONE 0 +#define R_ALPHA_REFLONG 1 +#define R_ALPHA_REFQUAD 2 +#define R_ALPHA_GPREL32 3 +#define R_ALPHA_LITERAL 4 +#define R_ALPHA_LITUSE 5 +#define R_ALPHA_GPDISP 6 +#define R_ALPHA_BRADDR 7 +#define R_ALPHA_HINT 8 +#define R_ALPHA_SREL16 9 +#define R_ALPHA_SREL32 10 +#define R_ALPHA_SREL64 11 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_GPREL16 19 +#define R_ALPHA_COPY 24 +#define R_ALPHA_GLOB_DAT 25 +#define R_ALPHA_JMP_SLOT 26 +#define R_ALPHA_RELATIVE 27 +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 + +#define R_ALPHA_NUM 46 + + +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + + +#define DT_ALPHA_PLTRO (DT_LOPROC + 0) +#define DT_ALPHA_NUM 1 + + + + +#define EF_PPC_EMB 0x80000000 + + +#define EF_PPC_RELOCATABLE 0x00010000 +#define EF_PPC_RELOCATABLE_LIB 0x00008000 + + + +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + + +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 +#define R_PPC_GOT_DTPREL16 91 +#define R_PPC_GOT_DTPREL16_LO 92 +#define R_PPC_GOT_DTPREL16_HI 93 +#define R_PPC_GOT_DTPREL16_HA 94 +#define R_PPC_TLSGD 95 +#define R_PPC_TLSLD 96 + + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + + +#define R_PPC_DIAB_SDA21_LO 180 +#define R_PPC_DIAB_SDA21_HI 181 +#define R_PPC_DIAB_SDA21_HA 182 +#define R_PPC_DIAB_RELSDA_LO 183 +#define R_PPC_DIAB_RELSDA_HI 184 +#define R_PPC_DIAB_RELSDA_HA 185 + + +#define R_PPC_IRELATIVE 248 + + +#define R_PPC_REL16 249 +#define R_PPC_REL16_LO 250 +#define R_PPC_REL16_HI 251 +#define R_PPC_REL16_HA 252 + + + +#define R_PPC_TOC16 255 + + +#define DT_PPC_GOT (DT_LOPROC + 0) +#define DT_PPC_OPT (DT_LOPROC + 1) +#define DT_PPC_NUM 2 + +#define PPC_OPT_TLS 1 + + +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 +#define R_PPC64_ADDR24 R_PPC_ADDR24 +#define R_PPC64_ADDR16 R_PPC_ADDR16 +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA +#define R_PPC64_ADDR14 R_PPC_ADDR14 +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 +#define R_PPC64_REL14 R_PPC_REL14 +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_PLTGOT16 52 +#define R_PPC64_PLTGOT16_LO 53 +#define R_PPC64_PLTGOT16_HI 54 +#define R_PPC64_PLTGOT16_HA 55 + +#define R_PPC64_ADDR16_DS 56 +#define R_PPC64_ADDR16_LO_DS 57 +#define R_PPC64_GOT16_DS 58 +#define R_PPC64_GOT16_LO_DS 59 +#define R_PPC64_PLT16_LO_DS 60 +#define R_PPC64_SECTOFF_DS 61 +#define R_PPC64_SECTOFF_LO_DS 62 +#define R_PPC64_TOC16_DS 63 +#define R_PPC64_TOC16_LO_DS 64 +#define R_PPC64_PLTGOT16_DS 65 +#define R_PPC64_PLTGOT16_LO_DS 66 + + +#define R_PPC64_TLS 67 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL16 69 +#define R_PPC64_TPREL16_LO 70 +#define R_PPC64_TPREL16_HI 71 +#define R_PPC64_TPREL16_HA 72 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL16 74 +#define R_PPC64_DTPREL16_LO 75 +#define R_PPC64_DTPREL16_HI 76 +#define R_PPC64_DTPREL16_HA 77 +#define R_PPC64_DTPREL64 78 +#define R_PPC64_GOT_TLSGD16 79 +#define R_PPC64_GOT_TLSGD16_LO 80 +#define R_PPC64_GOT_TLSGD16_HI 81 +#define R_PPC64_GOT_TLSGD16_HA 82 +#define R_PPC64_GOT_TLSLD16 83 +#define R_PPC64_GOT_TLSLD16_LO 84 +#define R_PPC64_GOT_TLSLD16_HI 85 +#define R_PPC64_GOT_TLSLD16_HA 86 +#define R_PPC64_GOT_TPREL16_DS 87 +#define R_PPC64_GOT_TPREL16_LO_DS 88 +#define R_PPC64_GOT_TPREL16_HI 89 +#define R_PPC64_GOT_TPREL16_HA 90 +#define R_PPC64_GOT_DTPREL16_DS 91 +#define R_PPC64_GOT_DTPREL16_LO_DS 92 +#define R_PPC64_GOT_DTPREL16_HI 93 +#define R_PPC64_GOT_DTPREL16_HA 94 +#define R_PPC64_TPREL16_DS 95 +#define R_PPC64_TPREL16_LO_DS 96 +#define R_PPC64_TPREL16_HIGHER 97 +#define R_PPC64_TPREL16_HIGHERA 98 +#define R_PPC64_TPREL16_HIGHEST 99 +#define R_PPC64_TPREL16_HIGHESTA 100 +#define R_PPC64_DTPREL16_DS 101 +#define R_PPC64_DTPREL16_LO_DS 102 +#define R_PPC64_DTPREL16_HIGHER 103 +#define R_PPC64_DTPREL16_HIGHERA 104 +#define R_PPC64_DTPREL16_HIGHEST 105 +#define R_PPC64_DTPREL16_HIGHESTA 106 +#define R_PPC64_TLSGD 107 +#define R_PPC64_TLSLD 108 +#define R_PPC64_TOCSAVE 109 +#define R_PPC64_ADDR16_HIGH 110 +#define R_PPC64_ADDR16_HIGHA 111 +#define R_PPC64_TPREL16_HIGH 112 +#define R_PPC64_TPREL16_HIGHA 113 +#define R_PPC64_DTPREL16_HIGH 114 +#define R_PPC64_DTPREL16_HIGHA 115 + + +#define R_PPC64_JMP_IREL 247 +#define R_PPC64_IRELATIVE 248 +#define R_PPC64_REL16 249 +#define R_PPC64_REL16_LO 250 +#define R_PPC64_REL16_HI 251 +#define R_PPC64_REL16_HA 252 + +#define EF_PPC64_ABI 3 + +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_OPD (DT_LOPROC + 1) +#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +#define DT_PPC64_OPT (DT_LOPROC + 3) +#define DT_PPC64_NUM 4 + +#define PPC64_OPT_TLS 1 +#define PPC64_OPT_MULTI_TOC 2 +#define PPC64_OPT_LOCALENTRY 4 + +#define STO_PPC64_LOCAL_BIT 5 +#define STO_PPC64_LOCAL_MASK 0xe0 +#define PPC64_LOCAL_ENTRY_OFFSET(x) (1 << (((x)&0xe0)>>5) & 0xfc) + + +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_SOFT_FLOAT 0x200 +#define EF_ARM_VFP_FLOAT 0x400 +#define EF_ARM_MAVERICK_FLOAT 0x800 + +#define EF_ARM_ABI_FLOAT_SOFT 0x200 +#define EF_ARM_ABI_FLOAT_HARD 0x400 + + +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + + +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_LE8 0x00400000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 + + +#define STT_ARM_TFUNC STT_LOPROC +#define STT_ARM_16BIT STT_HIPROC + + +#define SHF_ARM_ENTRYSECT 0x10000000 +#define SHF_ARM_COMDEF 0x80000000 + + + +#define PF_ARM_SB 0x10000000 + +#define PF_ARM_PI 0x20000000 +#define PF_ARM_ABS 0x40000000 + + +#define PT_ARM_EXIDX (PT_LOPROC + 1) + + +#define SHT_ARM_EXIDX (SHT_LOPROC + 1) +#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) +#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) + +#define R_AARCH64_NONE 0 +#define R_AARCH64_P32_ABS32 1 +#define R_AARCH64_P32_COPY 180 +#define R_AARCH64_P32_GLOB_DAT 181 +#define R_AARCH64_P32_JUMP_SLOT 182 +#define R_AARCH64_P32_RELATIVE 183 +#define R_AARCH64_P32_TLS_DTPMOD 184 +#define R_AARCH64_P32_TLS_DTPREL 185 +#define R_AARCH64_P32_TLS_TPREL 186 +#define R_AARCH64_P32_TLSDESC 187 +#define R_AARCH64_P32_IRELATIVE 188 +#define R_AARCH64_ABS64 257 +#define R_AARCH64_ABS32 258 +#define R_AARCH64_ABS16 259 +#define R_AARCH64_PREL64 260 +#define R_AARCH64_PREL32 261 +#define R_AARCH64_PREL16 262 +#define R_AARCH64_MOVW_UABS_G0 263 +#define R_AARCH64_MOVW_UABS_G0_NC 264 +#define R_AARCH64_MOVW_UABS_G1 265 +#define R_AARCH64_MOVW_UABS_G1_NC 266 +#define R_AARCH64_MOVW_UABS_G2 267 +#define R_AARCH64_MOVW_UABS_G2_NC 268 +#define R_AARCH64_MOVW_UABS_G3 269 +#define R_AARCH64_MOVW_SABS_G0 270 +#define R_AARCH64_MOVW_SABS_G1 271 +#define R_AARCH64_MOVW_SABS_G2 272 +#define R_AARCH64_LD_PREL_LO19 273 +#define R_AARCH64_ADR_PREL_LO21 274 +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_LDST8_ABS_LO12_NC 278 +#define R_AARCH64_TSTBR14 279 +#define R_AARCH64_CONDBR19 280 +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 +#define R_AARCH64_MOVW_PREL_G0 287 +#define R_AARCH64_MOVW_PREL_G0_NC 288 +#define R_AARCH64_MOVW_PREL_G1 289 +#define R_AARCH64_MOVW_PREL_G1_NC 290 +#define R_AARCH64_MOVW_PREL_G2 291 +#define R_AARCH64_MOVW_PREL_G2_NC 292 +#define R_AARCH64_MOVW_PREL_G3 293 +#define R_AARCH64_LDST128_ABS_LO12_NC 299 +#define R_AARCH64_MOVW_GOTOFF_G0 300 +#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 +#define R_AARCH64_MOVW_GOTOFF_G1 302 +#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 +#define R_AARCH64_MOVW_GOTOFF_G2 304 +#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 +#define R_AARCH64_MOVW_GOTOFF_G3 306 +#define R_AARCH64_GOTREL64 307 +#define R_AARCH64_GOTREL32 308 +#define R_AARCH64_GOT_LD_PREL19 309 +#define R_AARCH64_LD64_GOTOFF_LO15 310 +#define R_AARCH64_ADR_GOT_PAGE 311 +#define R_AARCH64_LD64_GOT_LO12_NC 312 +#define R_AARCH64_LD64_GOTPAGE_LO15 313 +#define R_AARCH64_TLSGD_ADR_PREL21 512 +#define R_AARCH64_TLSGD_ADR_PAGE21 513 +#define R_AARCH64_TLSGD_ADD_LO12_NC 514 +#define R_AARCH64_TLSGD_MOVW_G1 515 +#define R_AARCH64_TLSGD_MOVW_G0_NC 516 +#define R_AARCH64_TLSLD_ADR_PREL21 517 +#define R_AARCH64_TLSLD_ADR_PAGE21 518 +#define R_AARCH64_TLSLD_ADD_LO12_NC 519 +#define R_AARCH64_TLSLD_MOVW_G1 520 +#define R_AARCH64_TLSLD_MOVW_G0_NC 521 +#define R_AARCH64_TLSLD_LD_PREL19 522 +#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 +#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 +#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 +#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 +#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 +#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 +#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 +#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 +#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 +#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 +#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 +#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 +#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 +#define R_AARCH64_TLSDESC_LD_PREL19 560 +#define R_AARCH64_TLSDESC_ADR_PREL21 561 +#define R_AARCH64_TLSDESC_ADR_PAGE21 562 +#define R_AARCH64_TLSDESC_LD64_LO12 563 +#define R_AARCH64_TLSDESC_ADD_LO12 564 +#define R_AARCH64_TLSDESC_OFF_G1 565 +#define R_AARCH64_TLSDESC_OFF_G0_NC 566 +#define R_AARCH64_TLSDESC_LDR 567 +#define R_AARCH64_TLSDESC_ADD 568 +#define R_AARCH64_TLSDESC_CALL 569 +#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 +#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 +#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 +#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 +#define R_AARCH64_JUMP_SLOT 1026 +#define R_AARCH64_RELATIVE 1027 +#define R_AARCH64_TLS_DTPMOD 1028 +#define R_AARCH64_TLS_DTPMOD64 1028 +#define R_AARCH64_TLS_DTPREL 1029 +#define R_AARCH64_TLS_DTPREL64 1029 +#define R_AARCH64_TLS_TPREL 1030 +#define R_AARCH64_TLS_TPREL64 1030 +#define R_AARCH64_TLSDESC 1031 + + +#define R_ARM_NONE 0 +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_TLS_DESC 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_TLS_DTPMOD32 17 +#define R_ARM_TLS_DTPOFF32 18 +#define R_ARM_TLS_TPOFF32 19 +#define R_ARM_COPY 20 +#define R_ARM_GLOB_DAT 21 +#define R_ARM_JUMP_SLOT 22 +#define R_ARM_RELATIVE 23 +#define R_ARM_GOTOFF 24 +#define R_ARM_GOTPC 25 +#define R_ARM_GOT32 26 +#define R_ARM_PLT32 27 +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_THM_JUMP24 30 +#define R_ARM_BASE_ABS 31 +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_TARGET1 38 +#define R_ARM_SBREL31 39 +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 +#define R_ARM_MOVW_ABS_NC 43 +#define R_ARM_MOVT_ABS 44 +#define R_ARM_MOVW_PREL_NC 45 +#define R_ARM_MOVT_PREL 46 +#define R_ARM_THM_MOVW_ABS_NC 47 +#define R_ARM_THM_MOVT_ABS 48 +#define R_ARM_THM_MOVW_PREL_NC 49 +#define R_ARM_THM_MOVT_PREL 50 +#define R_ARM_THM_JUMP19 51 +#define R_ARM_THM_JUMP6 52 +#define R_ARM_THM_ALU_PREL_11_0 53 +#define R_ARM_THM_PC12 54 +#define R_ARM_ABS32_NOI 55 +#define R_ARM_REL32_NOI 56 +#define R_ARM_ALU_PC_G0_NC 57 +#define R_ARM_ALU_PC_G0 58 +#define R_ARM_ALU_PC_G1_NC 59 +#define R_ARM_ALU_PC_G1 60 +#define R_ARM_ALU_PC_G2 61 +#define R_ARM_LDR_PC_G1 62 +#define R_ARM_LDR_PC_G2 63 +#define R_ARM_LDRS_PC_G0 64 +#define R_ARM_LDRS_PC_G1 65 +#define R_ARM_LDRS_PC_G2 66 +#define R_ARM_LDC_PC_G0 67 +#define R_ARM_LDC_PC_G1 68 +#define R_ARM_LDC_PC_G2 69 +#define R_ARM_ALU_SB_G0_NC 70 +#define R_ARM_ALU_SB_G0 71 +#define R_ARM_ALU_SB_G1_NC 72 +#define R_ARM_ALU_SB_G1 73 +#define R_ARM_ALU_SB_G2 74 +#define R_ARM_LDR_SB_G0 75 +#define R_ARM_LDR_SB_G1 76 +#define R_ARM_LDR_SB_G2 77 +#define R_ARM_LDRS_SB_G0 78 +#define R_ARM_LDRS_SB_G1 79 +#define R_ARM_LDRS_SB_G2 80 +#define R_ARM_LDC_SB_G0 81 +#define R_ARM_LDC_SB_G1 82 +#define R_ARM_LDC_SB_G2 83 +#define R_ARM_MOVW_BREL_NC 84 +#define R_ARM_MOVT_BREL 85 +#define R_ARM_MOVW_BREL 86 +#define R_ARM_THM_MOVW_BREL_NC 87 +#define R_ARM_THM_MOVT_BREL 88 +#define R_ARM_THM_MOVW_BREL 89 +#define R_ARM_TLS_GOTDESC 90 +#define R_ARM_TLS_CALL 91 +#define R_ARM_TLS_DESCSEQ 92 +#define R_ARM_THM_TLS_CALL 93 +#define R_ARM_PLT32_ABS 94 +#define R_ARM_GOT_ABS 95 +#define R_ARM_GOT_PREL 96 +#define R_ARM_GOT_BREL12 97 +#define R_ARM_GOTOFF12 98 +#define R_ARM_GOTRELAX 99 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 +#define R_ARM_THM_PC9 103 +#define R_ARM_TLS_GD32 104 + +#define R_ARM_TLS_LDM32 105 + +#define R_ARM_TLS_LDO32 106 + +#define R_ARM_TLS_IE32 107 + +#define R_ARM_TLS_LE32 108 +#define R_ARM_TLS_LDO12 109 +#define R_ARM_TLS_LE12 110 +#define R_ARM_TLS_IE12GP 111 +#define R_ARM_ME_TOO 128 +#define R_ARM_THM_TLS_DESCSEQ 129 +#define R_ARM_THM_TLS_DESCSEQ16 129 +#define R_ARM_THM_TLS_DESCSEQ32 130 +#define R_ARM_THM_GOT_BREL12 131 +#define R_ARM_IRELATIVE 160 +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +#define R_ARM_NUM 256 + + +#define R_CKCORE_NONE 0 +#define R_CKCORE_ADDR32 1 +#define R_CKCORE_PCRELIMM8BY4 2 +#define R_CKCORE_PCRELIMM11BY2 3 +#define R_CKCORE_PCREL32 5 +#define R_CKCORE_PCRELJSR_IMM11BY2 6 +#define R_CKCORE_RELATIVE 9 +#define R_CKCORE_COPY 10 +#define R_CKCORE_GLOB_DAT 11 +#define R_CKCORE_JUMP_SLOT 12 +#define R_CKCORE_GOTOFF 13 +#define R_CKCORE_GOTPC 14 +#define R_CKCORE_GOT32 15 +#define R_CKCORE_PLT32 16 +#define R_CKCORE_ADDRGOT 17 +#define R_CKCORE_ADDRPLT 18 +#define R_CKCORE_PCREL_IMM26BY2 19 +#define R_CKCORE_PCREL_IMM16BY2 20 +#define R_CKCORE_PCREL_IMM16BY4 21 +#define R_CKCORE_PCREL_IMM10BY2 22 +#define R_CKCORE_PCREL_IMM10BY4 23 +#define R_CKCORE_ADDR_HI16 24 +#define R_CKCORE_ADDR_LO16 25 +#define R_CKCORE_GOTPC_HI16 26 +#define R_CKCORE_GOTPC_LO16 27 +#define R_CKCORE_GOTOFF_HI16 28 +#define R_CKCORE_GOTOFF_LO16 29 +#define R_CKCORE_GOT12 30 +#define R_CKCORE_GOT_HI16 31 +#define R_CKCORE_GOT_LO16 32 +#define R_CKCORE_PLT12 33 +#define R_CKCORE_PLT_HI16 34 +#define R_CKCORE_PLT_LO16 35 +#define R_CKCORE_ADDRGOT_HI16 36 +#define R_CKCORE_ADDRGOT_LO16 37 +#define R_CKCORE_ADDRPLT_HI16 38 +#define R_CKCORE_ADDRPLT_LO16 39 +#define R_CKCORE_PCREL_JSR_IMM26BY2 40 +#define R_CKCORE_TOFFSET_LO16 41 +#define R_CKCORE_DOFFSET_LO16 42 +#define R_CKCORE_PCREL_IMM18BY2 43 +#define R_CKCORE_DOFFSET_IMM18 44 +#define R_CKCORE_DOFFSET_IMM18BY2 45 +#define R_CKCORE_DOFFSET_IMM18BY4 46 +#define R_CKCORE_GOT_IMM18BY4 48 +#define R_CKCORE_PLT_IMM18BY4 49 +#define R_CKCORE_PCREL_IMM7BY4 50 +#define R_CKCORE_TLS_LE32 51 +#define R_CKCORE_TLS_IE32 52 +#define R_CKCORE_TLS_GD32 53 +#define R_CKCORE_TLS_LDM32 54 +#define R_CKCORE_TLS_LDO32 55 +#define R_CKCORE_TLS_DTPMOD32 56 +#define R_CKCORE_TLS_DTPOFF32 57 +#define R_CKCORE_TLS_TPOFF32 58 + + +#define EF_IA_64_MASKOS 0x0000000f +#define EF_IA_64_ABI64 0x00000010 +#define EF_IA_64_ARCH 0xff000000 + + +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) +#define PT_IA_64_UNWIND (PT_LOPROC + 1) +#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) + + +#define PF_IA_64_NORECOV 0x80000000 + + +#define SHT_IA_64_EXT (SHT_LOPROC + 0) +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) + + +#define SHF_IA_64_SHORT 0x10000000 +#define SHF_IA_64_NORECOV 0x20000000 + + +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + + +#define R_IA64_NONE 0x00 +#define R_IA64_IMM14 0x21 +#define R_IA64_IMM22 0x22 +#define R_IA64_IMM64 0x23 +#define R_IA64_DIR32MSB 0x24 +#define R_IA64_DIR32LSB 0x25 +#define R_IA64_DIR64MSB 0x26 +#define R_IA64_DIR64LSB 0x27 +#define R_IA64_GPREL22 0x2a +#define R_IA64_GPREL64I 0x2b +#define R_IA64_GPREL32MSB 0x2c +#define R_IA64_GPREL32LSB 0x2d +#define R_IA64_GPREL64MSB 0x2e +#define R_IA64_GPREL64LSB 0x2f +#define R_IA64_LTOFF22 0x32 +#define R_IA64_LTOFF64I 0x33 +#define R_IA64_PLTOFF22 0x3a +#define R_IA64_PLTOFF64I 0x3b +#define R_IA64_PLTOFF64MSB 0x3e +#define R_IA64_PLTOFF64LSB 0x3f +#define R_IA64_FPTR64I 0x43 +#define R_IA64_FPTR32MSB 0x44 +#define R_IA64_FPTR32LSB 0x45 +#define R_IA64_FPTR64MSB 0x46 +#define R_IA64_FPTR64LSB 0x47 +#define R_IA64_PCREL60B 0x48 +#define R_IA64_PCREL21B 0x49 +#define R_IA64_PCREL21M 0x4a +#define R_IA64_PCREL21F 0x4b +#define R_IA64_PCREL32MSB 0x4c +#define R_IA64_PCREL32LSB 0x4d +#define R_IA64_PCREL64MSB 0x4e +#define R_IA64_PCREL64LSB 0x4f +#define R_IA64_LTOFF_FPTR22 0x52 +#define R_IA64_LTOFF_FPTR64I 0x53 +#define R_IA64_LTOFF_FPTR32MSB 0x54 +#define R_IA64_LTOFF_FPTR32LSB 0x55 +#define R_IA64_LTOFF_FPTR64MSB 0x56 +#define R_IA64_LTOFF_FPTR64LSB 0x57 +#define R_IA64_SEGREL32MSB 0x5c +#define R_IA64_SEGREL32LSB 0x5d +#define R_IA64_SEGREL64MSB 0x5e +#define R_IA64_SEGREL64LSB 0x5f +#define R_IA64_SECREL32MSB 0x64 +#define R_IA64_SECREL32LSB 0x65 +#define R_IA64_SECREL64MSB 0x66 +#define R_IA64_SECREL64LSB 0x67 +#define R_IA64_REL32MSB 0x6c +#define R_IA64_REL32LSB 0x6d +#define R_IA64_REL64MSB 0x6e +#define R_IA64_REL64LSB 0x6f +#define R_IA64_LTV32MSB 0x74 +#define R_IA64_LTV32LSB 0x75 +#define R_IA64_LTV64MSB 0x76 +#define R_IA64_LTV64LSB 0x77 +#define R_IA64_PCREL21BI 0x79 +#define R_IA64_PCREL22 0x7a +#define R_IA64_PCREL64I 0x7b +#define R_IA64_IPLTMSB 0x80 +#define R_IA64_IPLTLSB 0x81 +#define R_IA64_COPY 0x84 +#define R_IA64_SUB 0x85 +#define R_IA64_LTOFF22X 0x86 +#define R_IA64_LDXMOV 0x87 +#define R_IA64_TPREL14 0x91 +#define R_IA64_TPREL22 0x92 +#define R_IA64_TPREL64I 0x93 +#define R_IA64_TPREL64MSB 0x96 +#define R_IA64_TPREL64LSB 0x97 +#define R_IA64_LTOFF_TPREL22 0x9a +#define R_IA64_DTPMOD64MSB 0xa6 +#define R_IA64_DTPMOD64LSB 0xa7 +#define R_IA64_LTOFF_DTPMOD22 0xaa +#define R_IA64_DTPREL14 0xb1 +#define R_IA64_DTPREL22 0xb2 +#define R_IA64_DTPREL64I 0xb3 +#define R_IA64_DTPREL32MSB 0xb4 +#define R_IA64_DTPREL32LSB 0xb5 +#define R_IA64_DTPREL64MSB 0xb6 +#define R_IA64_DTPREL64LSB 0xb7 +#define R_IA64_LTOFF_DTPREL22 0xba + + +#define EF_SH_MACH_MASK 0x1f +#define EF_SH_UNKNOWN 0x0 +#define EF_SH1 0x1 +#define EF_SH2 0x2 +#define EF_SH3 0x3 +#define EF_SH_DSP 0x4 +#define EF_SH3_DSP 0x5 +#define EF_SH4AL_DSP 0x6 +#define EF_SH3E 0x8 +#define EF_SH4 0x9 +#define EF_SH2E 0xb +#define EF_SH4A 0xc +#define EF_SH2A 0xd +#define EF_SH4_NOFPU 0x10 +#define EF_SH4A_NOFPU 0x11 +#define EF_SH4_NOMMU_NOFPU 0x12 +#define EF_SH2A_NOFPU 0x13 +#define EF_SH3_NOMMU 0x14 +#define EF_SH2A_SH4_NOFPU 0x15 +#define EF_SH2A_SH3_NOFPU 0x16 +#define EF_SH2A_SH4 0x17 +#define EF_SH2A_SH3E 0x18 + +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +#define R_SH_GOT20 201 +#define R_SH_GOTOFF20 202 +#define R_SH_GOTFUNCDESC 203 +#define R_SH_GOTFUNCDEST20 204 +#define R_SH_GOTOFFFUNCDESC 205 +#define R_SH_GOTOFFFUNCDEST20 206 +#define R_SH_FUNCDESC 207 +#define R_SH_FUNCDESC_VALUE 208 + +#define R_SH_NUM 256 + + + +#define R_390_NONE 0 +#define R_390_8 1 +#define R_390_12 2 +#define R_390_16 3 +#define R_390_32 4 +#define R_390_PC32 5 +#define R_390_GOT12 6 +#define R_390_GOT32 7 +#define R_390_PLT32 8 +#define R_390_COPY 9 +#define R_390_GLOB_DAT 10 +#define R_390_JMP_SLOT 11 +#define R_390_RELATIVE 12 +#define R_390_GOTOFF32 13 +#define R_390_GOTPC 14 +#define R_390_GOT16 15 +#define R_390_PC16 16 +#define R_390_PC16DBL 17 +#define R_390_PLT16DBL 18 +#define R_390_PC32DBL 19 +#define R_390_PLT32DBL 20 +#define R_390_GOTPCDBL 21 +#define R_390_64 22 +#define R_390_PC64 23 +#define R_390_GOT64 24 +#define R_390_PLT64 25 +#define R_390_GOTENT 26 +#define R_390_GOTOFF16 27 +#define R_390_GOTOFF64 28 +#define R_390_GOTPLT12 29 +#define R_390_GOTPLT16 30 +#define R_390_GOTPLT32 31 +#define R_390_GOTPLT64 32 +#define R_390_GOTPLTENT 33 +#define R_390_PLTOFF16 34 +#define R_390_PLTOFF32 35 +#define R_390_PLTOFF64 36 +#define R_390_TLS_LOAD 37 +#define R_390_TLS_GDCALL 38 + +#define R_390_TLS_LDCALL 39 + +#define R_390_TLS_GD32 40 + +#define R_390_TLS_GD64 41 + +#define R_390_TLS_GOTIE12 42 + +#define R_390_TLS_GOTIE32 43 + +#define R_390_TLS_GOTIE64 44 + +#define R_390_TLS_LDM32 45 + +#define R_390_TLS_LDM64 46 + +#define R_390_TLS_IE32 47 + +#define R_390_TLS_IE64 48 + +#define R_390_TLS_IEENT 49 + +#define R_390_TLS_LE32 50 + +#define R_390_TLS_LE64 51 + +#define R_390_TLS_LDO32 52 + +#define R_390_TLS_LDO64 53 + +#define R_390_TLS_DTPMOD 54 +#define R_390_TLS_DTPOFF 55 +#define R_390_TLS_TPOFF 56 + +#define R_390_20 57 +#define R_390_GOT20 58 +#define R_390_GOTPLT20 59 +#define R_390_TLS_GOTIE20 60 + + +#define R_390_NUM 61 + + + +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +#define R_CRIS_NUM 20 + + + +#define R_X86_64_NONE 0 +#define R_X86_64_64 1 +#define R_X86_64_PC32 2 +#define R_X86_64_GOT32 3 +#define R_X86_64_PLT32 4 +#define R_X86_64_COPY 5 +#define R_X86_64_GLOB_DAT 6 +#define R_X86_64_JUMP_SLOT 7 +#define R_X86_64_RELATIVE 8 +#define R_X86_64_GOTPCREL 9 + +#define R_X86_64_32 10 +#define R_X86_64_32S 11 +#define R_X86_64_16 12 +#define R_X86_64_PC16 13 +#define R_X86_64_8 14 +#define R_X86_64_PC8 15 +#define R_X86_64_DTPMOD64 16 +#define R_X86_64_DTPOFF64 17 +#define R_X86_64_TPOFF64 18 +#define R_X86_64_TLSGD 19 + +#define R_X86_64_TLSLD 20 + +#define R_X86_64_DTPOFF32 21 +#define R_X86_64_GOTTPOFF 22 + +#define R_X86_64_TPOFF32 23 +#define R_X86_64_PC64 24 +#define R_X86_64_GOTOFF64 25 +#define R_X86_64_GOTPC32 26 +#define R_X86_64_GOT64 27 +#define R_X86_64_GOTPCREL64 28 +#define R_X86_64_GOTPC64 29 +#define R_X86_64_GOTPLT64 30 +#define R_X86_64_PLTOFF64 31 +#define R_X86_64_SIZE32 32 +#define R_X86_64_SIZE64 33 + +#define R_X86_64_GOTPC32_TLSDESC 34 +#define R_X86_64_TLSDESC_CALL 35 + +#define R_X86_64_TLSDESC 36 +#define R_X86_64_IRELATIVE 37 +#define R_X86_64_RELATIVE64 38 +#define R_X86_64_GOTPCRELX 41 +#define R_X86_64_REX_GOTPCRELX 42 +#define R_X86_64_NUM 43 + + + +#define R_MN10300_NONE 0 +#define R_MN10300_32 1 +#define R_MN10300_16 2 +#define R_MN10300_8 3 +#define R_MN10300_PCREL32 4 +#define R_MN10300_PCREL16 5 +#define R_MN10300_PCREL8 6 +#define R_MN10300_GNU_VTINHERIT 7 +#define R_MN10300_GNU_VTENTRY 8 +#define R_MN10300_24 9 +#define R_MN10300_GOTPC32 10 +#define R_MN10300_GOTPC16 11 +#define R_MN10300_GOTOFF32 12 +#define R_MN10300_GOTOFF24 13 +#define R_MN10300_GOTOFF16 14 +#define R_MN10300_PLT32 15 +#define R_MN10300_PLT16 16 +#define R_MN10300_GOT32 17 +#define R_MN10300_GOT24 18 +#define R_MN10300_GOT16 19 +#define R_MN10300_COPY 20 +#define R_MN10300_GLOB_DAT 21 +#define R_MN10300_JMP_SLOT 22 +#define R_MN10300_RELATIVE 23 + +#define R_MN10300_NUM 24 + + + +#define R_M32R_NONE 0 +#define R_M32R_16 1 +#define R_M32R_32 2 +#define R_M32R_24 3 +#define R_M32R_10_PCREL 4 +#define R_M32R_18_PCREL 5 +#define R_M32R_26_PCREL 6 +#define R_M32R_HI16_ULO 7 +#define R_M32R_HI16_SLO 8 +#define R_M32R_LO16 9 +#define R_M32R_SDA16 10 +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 + +#define R_M32R_16_RELA 33 +#define R_M32R_32_RELA 34 +#define R_M32R_24_RELA 35 +#define R_M32R_10_PCREL_RELA 36 +#define R_M32R_18_PCREL_RELA 37 +#define R_M32R_26_PCREL_RELA 38 +#define R_M32R_HI16_ULO_RELA 39 +#define R_M32R_HI16_SLO_RELA 40 +#define R_M32R_LO16_RELA 41 +#define R_M32R_SDA16_RELA 42 +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 +#define R_M32R_REL32 45 + +#define R_M32R_GOT24 48 +#define R_M32R_26_PLTREL 49 +#define R_M32R_COPY 50 +#define R_M32R_GLOB_DAT 51 +#define R_M32R_JMP_SLOT 52 +#define R_M32R_RELATIVE 53 +#define R_M32R_GOTOFF 54 +#define R_M32R_GOTPC24 55 +#define R_M32R_GOT16_HI_ULO 56 + +#define R_M32R_GOT16_HI_SLO 57 + +#define R_M32R_GOT16_LO 58 +#define R_M32R_GOTPC_HI_ULO 59 + +#define R_M32R_GOTPC_HI_SLO 60 + +#define R_M32R_GOTPC_LO 61 + +#define R_M32R_GOTOFF_HI_ULO 62 + +#define R_M32R_GOTOFF_HI_SLO 63 + +#define R_M32R_GOTOFF_LO 64 +#define R_M32R_NUM 256 + +#define R_MICROBLAZE_NONE 0 +#define R_MICROBLAZE_32 1 +#define R_MICROBLAZE_32_PCREL 2 +#define R_MICROBLAZE_64_PCREL 3 +#define R_MICROBLAZE_32_PCREL_LO 4 +#define R_MICROBLAZE_64 5 +#define R_MICROBLAZE_32_LO 6 +#define R_MICROBLAZE_SRO32 7 +#define R_MICROBLAZE_SRW32 8 +#define R_MICROBLAZE_64_NONE 9 +#define R_MICROBLAZE_32_SYM_OP_SYM 10 +#define R_MICROBLAZE_GNU_VTINHERIT 11 +#define R_MICROBLAZE_GNU_VTENTRY 12 +#define R_MICROBLAZE_GOTPC_64 13 +#define R_MICROBLAZE_GOT_64 14 +#define R_MICROBLAZE_PLT_64 15 +#define R_MICROBLAZE_REL 16 +#define R_MICROBLAZE_JUMP_SLOT 17 +#define R_MICROBLAZE_GLOB_DAT 18 +#define R_MICROBLAZE_GOTOFF_64 19 +#define R_MICROBLAZE_GOTOFF_32 20 +#define R_MICROBLAZE_COPY 21 +#define R_MICROBLAZE_TLS 22 +#define R_MICROBLAZE_TLSGD 23 +#define R_MICROBLAZE_TLSLD 24 +#define R_MICROBLAZE_TLSDTPMOD32 25 +#define R_MICROBLAZE_TLSDTPREL32 26 +#define R_MICROBLAZE_TLSDTPREL64 27 +#define R_MICROBLAZE_TLSGOTTPREL32 28 +#define R_MICROBLAZE_TLSTPREL32 29 + +#define DT_NIOS2_GP 0x70000002 + +#define R_NIOS2_NONE 0 +#define R_NIOS2_S16 1 +#define R_NIOS2_U16 2 +#define R_NIOS2_PCREL16 3 +#define R_NIOS2_CALL26 4 +#define R_NIOS2_IMM5 5 +#define R_NIOS2_CACHE_OPX 6 +#define R_NIOS2_IMM6 7 +#define R_NIOS2_IMM8 8 +#define R_NIOS2_HI16 9 +#define R_NIOS2_LO16 10 +#define R_NIOS2_HIADJ16 11 +#define R_NIOS2_BFD_RELOC_32 12 +#define R_NIOS2_BFD_RELOC_16 13 +#define R_NIOS2_BFD_RELOC_8 14 +#define R_NIOS2_GPREL 15 +#define R_NIOS2_GNU_VTINHERIT 16 +#define R_NIOS2_GNU_VTENTRY 17 +#define R_NIOS2_UJMP 18 +#define R_NIOS2_CJMP 19 +#define R_NIOS2_CALLR 20 +#define R_NIOS2_ALIGN 21 +#define R_NIOS2_GOT16 22 +#define R_NIOS2_CALL16 23 +#define R_NIOS2_GOTOFF_LO 24 +#define R_NIOS2_GOTOFF_HA 25 +#define R_NIOS2_PCREL_LO 26 +#define R_NIOS2_PCREL_HA 27 +#define R_NIOS2_TLS_GD16 28 +#define R_NIOS2_TLS_LDM16 29 +#define R_NIOS2_TLS_LDO16 30 +#define R_NIOS2_TLS_IE16 31 +#define R_NIOS2_TLS_LE16 32 +#define R_NIOS2_TLS_DTPMOD 33 +#define R_NIOS2_TLS_DTPREL 34 +#define R_NIOS2_TLS_TPREL 35 +#define R_NIOS2_COPY 36 +#define R_NIOS2_GLOB_DAT 37 +#define R_NIOS2_JUMP_SLOT 38 +#define R_NIOS2_RELATIVE 39 +#define R_NIOS2_GOTOFF 40 +#define R_NIOS2_CALL26_NOAT 41 +#define R_NIOS2_GOT_LO 42 +#define R_NIOS2_GOT_HA 43 +#define R_NIOS2_CALL_LO 44 +#define R_NIOS2_CALL_HA 45 + +#define R_OR1K_NONE 0 +#define R_OR1K_32 1 +#define R_OR1K_16 2 +#define R_OR1K_8 3 +#define R_OR1K_LO_16_IN_INSN 4 +#define R_OR1K_HI_16_IN_INSN 5 +#define R_OR1K_INSN_REL_26 6 +#define R_OR1K_GNU_VTENTRY 7 +#define R_OR1K_GNU_VTINHERIT 8 +#define R_OR1K_32_PCREL 9 +#define R_OR1K_16_PCREL 10 +#define R_OR1K_8_PCREL 11 +#define R_OR1K_GOTPC_HI16 12 +#define R_OR1K_GOTPC_LO16 13 +#define R_OR1K_GOT16 14 +#define R_OR1K_PLT26 15 +#define R_OR1K_GOTOFF_HI16 16 +#define R_OR1K_GOTOFF_LO16 17 +#define R_OR1K_COPY 18 +#define R_OR1K_GLOB_DAT 19 +#define R_OR1K_JMP_SLOT 20 +#define R_OR1K_RELATIVE 21 +#define R_OR1K_TLS_GD_HI16 22 +#define R_OR1K_TLS_GD_LO16 23 +#define R_OR1K_TLS_LDM_HI16 24 +#define R_OR1K_TLS_LDM_LO16 25 +#define R_OR1K_TLS_LDO_HI16 26 +#define R_OR1K_TLS_LDO_LO16 27 +#define R_OR1K_TLS_IE_HI16 28 +#define R_OR1K_TLS_IE_LO16 29 +#define R_OR1K_TLS_LE_HI16 30 +#define R_OR1K_TLS_LE_LO16 31 +#define R_OR1K_TLS_TPOFF 32 +#define R_OR1K_TLS_DTPOFF 33 +#define R_OR1K_TLS_DTPMOD 34 + +#define R_BPF_NONE 0 +#define R_BPF_MAP_FD 1 + +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 + +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 +#define R_RISCV_32_PCREL 57 + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/c/common/test/includes/standard-library/endian.h b/c/common/test/includes/standard-library/endian.h new file mode 100644 index 0000000000..172c43203a --- /dev/null +++ b/c/common/test/includes/standard-library/endian.h @@ -0,0 +1,80 @@ +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include + +#define __NEED_uint16_t +#define __NEED_uint32_t +#define __NEED_uint64_t + +#include + +#define __PDP_ENDIAN 3412 + +#define BIG_ENDIAN __BIG_ENDIAN +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +static __inline uint16_t __bswap16(uint16_t __x) +{ + return __x<<8 | __x>>8; +} + +static __inline uint32_t __bswap32(uint32_t __x) +{ + return __x>>24 | __x>>8&0xff00 | __x<<8&0xff0000 | __x<<24; +} + +static __inline uint64_t __bswap64(uint64_t __x) +{ + return __bswap32(__x)+0ULL<<32 | __bswap32(__x>>32); +} + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define htobe16(x) __bswap16(x) +#define be16toh(x) __bswap16(x) +#define htobe32(x) __bswap32(x) +#define be32toh(x) __bswap32(x) +#define htobe64(x) __bswap64(x) +#define be64toh(x) __bswap64(x) +#define htole16(x) (uint16_t)(x) +#define le16toh(x) (uint16_t)(x) +#define htole32(x) (uint32_t)(x) +#define le32toh(x) (uint32_t)(x) +#define htole64(x) (uint64_t)(x) +#define le64toh(x) (uint64_t)(x) +#else +#define htobe16(x) (uint16_t)(x) +#define be16toh(x) (uint16_t)(x) +#define htobe32(x) (uint32_t)(x) +#define be32toh(x) (uint32_t)(x) +#define htobe64(x) (uint64_t)(x) +#define be64toh(x) (uint64_t)(x) +#define htole16(x) __bswap16(x) +#define le16toh(x) __bswap16(x) +#define htole32(x) __bswap32(x) +#define le32toh(x) __bswap32(x) +#define htole64(x) __bswap64(x) +#define le64toh(x) __bswap64(x) +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define betoh16(x) __bswap16(x) +#define betoh32(x) __bswap32(x) +#define betoh64(x) __bswap64(x) +#define letoh16(x) (uint16_t)(x) +#define letoh32(x) (uint32_t)(x) +#define letoh64(x) (uint64_t)(x) +#else +#define betoh16(x) (uint16_t)(x) +#define betoh32(x) (uint32_t)(x) +#define betoh64(x) (uint64_t)(x) +#define letoh16(x) __bswap16(x) +#define letoh32(x) __bswap32(x) +#define letoh64(x) __bswap64(x) +#endif +#endif + +#endif diff --git a/c/common/test/includes/standard-library/err.h b/c/common/test/includes/standard-library/err.h new file mode 100644 index 0000000000..9f5cb6b9e9 --- /dev/null +++ b/c/common/test/includes/standard-library/err.h @@ -0,0 +1,25 @@ +#ifndef _ERR_H +#define _ERR_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void warn(const char *, ...); +void vwarn(const char *, va_list); +void warnx(const char *, ...); +void vwarnx(const char *, va_list); + +_Noreturn void err(int, const char *, ...); +_Noreturn void verr(int, const char *, va_list); +_Noreturn void errx(int, const char *, ...); +_Noreturn void verrx(int, const char *, va_list); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/errno.h b/c/common/test/includes/standard-library/errno.h new file mode 100644 index 0000000000..0361b33ad3 --- /dev/null +++ b/c/common/test/includes/standard-library/errno.h @@ -0,0 +1,27 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#ifdef __GNUC__ +__attribute__((const)) +#endif +int *__errno_location(void); +#define errno (*__errno_location()) + +#ifdef _GNU_SOURCE +extern char *program_invocation_short_name, *program_invocation_name; +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/c/common/test/includes/standard-library/fcntl.h b/c/common/test/includes/standard-library/fcntl.h new file mode 100644 index 0000000000..b664cdc441 --- /dev/null +++ b/c/common/test/includes/standard-library/fcntl.h @@ -0,0 +1,216 @@ +#ifndef _FCNTL_H +#define _FCNTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_off_t +#define __NEED_pid_t +#define __NEED_mode_t + +#ifdef _GNU_SOURCE +#define __NEED_size_t +#define __NEED_ssize_t +#define __NEED_struct_iovec +#endif + +#include + +#include + +struct flock { + short l_type; + short l_whence; + off_t l_start; + off_t l_len; + pid_t l_pid; +}; + +int creat(const char *, mode_t); +int fcntl(int, int, ...); +int open(const char *, int, ...); +int openat(int, const char *, int, ...); +int posix_fadvise(int, off_t, off_t, int); +int posix_fallocate(int, off_t, off_t); + +#define O_SEARCH O_PATH +#define O_EXEC O_PATH +#define O_TTY_INIT 0 + +#define O_ACCMODE (03|O_SEARCH) +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 + +#define F_OFD_GETLK 36 +#define F_OFD_SETLK 37 +#define F_OFD_SETLKW 38 + +#define F_DUPFD_CLOEXEC 1030 + +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +#define FD_CLOEXEC 1 + +#define AT_FDCWD (-100) +#define AT_SYMLINK_NOFOLLOW 0x100 +#define AT_REMOVEDIR 0x200 +#define AT_SYMLINK_FOLLOW 0x400 +#define AT_EACCESS 0x200 + +#define POSIX_FADV_NORMAL 0 +#define POSIX_FADV_RANDOM 1 +#define POSIX_FADV_SEQUENTIAL 2 +#define POSIX_FADV_WILLNEED 3 +#ifndef POSIX_FADV_DONTNEED +#define POSIX_FADV_DONTNEED 4 +#define POSIX_FADV_NOREUSE 5 +#endif + +#undef SEEK_SET +#undef SEEK_CUR +#undef SEEK_END +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#ifndef S_IRUSR +#define S_ISUID 04000 +#define S_ISGID 02000 +#define S_ISVTX 01000 +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#define S_IXUSR 0100 +#define S_IRWXU 0700 +#define S_IRGRP 0040 +#define S_IWGRP 0020 +#define S_IXGRP 0010 +#define S_IRWXG 0070 +#define S_IROTH 0004 +#define S_IWOTH 0002 +#define S_IXOTH 0001 +#define S_IRWXO 0007 +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define AT_NO_AUTOMOUNT 0x800 +#define AT_EMPTY_PATH 0x1000 +#define AT_STATX_SYNC_TYPE 0x6000 +#define AT_STATX_SYNC_AS_STAT 0x0000 +#define AT_STATX_FORCE_SYNC 0x2000 +#define AT_STATX_DONT_SYNC 0x4000 +#define AT_RECURSIVE 0x8000 + +#define FAPPEND O_APPEND +#define FFSYNC O_SYNC +#define FASYNC O_ASYNC +#define FNONBLOCK O_NONBLOCK +#define FNDELAY O_NDELAY + +#define F_OK 0 +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#define F_ULOCK 0 +#define F_LOCK 1 +#define F_TLOCK 2 +#define F_TEST 3 + +#define F_SETLEASE 1024 +#define F_GETLEASE 1025 +#define F_NOTIFY 1026 +#define F_CANCELLK 1029 +#define F_SETPIPE_SZ 1031 +#define F_GETPIPE_SZ 1032 +#define F_ADD_SEALS 1033 +#define F_GET_SEALS 1034 + +#define F_SEAL_SEAL 0x0001 +#define F_SEAL_SHRINK 0x0002 +#define F_SEAL_GROW 0x0004 +#define F_SEAL_WRITE 0x0008 +#define F_SEAL_FUTURE_WRITE 0x0010 + +#define F_GET_RW_HINT 1035 +#define F_SET_RW_HINT 1036 +#define F_GET_FILE_RW_HINT 1037 +#define F_SET_FILE_RW_HINT 1038 + +#define RWF_WRITE_LIFE_NOT_SET 0 +#define RWH_WRITE_LIFE_NONE 1 +#define RWH_WRITE_LIFE_SHORT 2 +#define RWH_WRITE_LIFE_MEDIUM 3 +#define RWH_WRITE_LIFE_LONG 4 +#define RWH_WRITE_LIFE_EXTREME 5 + +#define DN_ACCESS 0x00000001 +#define DN_MODIFY 0x00000002 +#define DN_CREATE 0x00000004 +#define DN_DELETE 0x00000008 +#define DN_RENAME 0x00000010 +#define DN_ATTRIB 0x00000020 +#define DN_MULTISHOT 0x80000000 + +int lockf(int, int, off_t); +#endif + +#if defined(_GNU_SOURCE) +#define F_OWNER_TID 0 +#define F_OWNER_PID 1 +#define F_OWNER_PGRP 2 +#define F_OWNER_GID 2 +struct file_handle { + unsigned handle_bytes; + int handle_type; + unsigned char f_handle[]; +}; +struct f_owner_ex { + int type; + pid_t pid; +}; +#define FALLOC_FL_KEEP_SIZE 1 +#define FALLOC_FL_PUNCH_HOLE 2 +#define MAX_HANDLE_SZ 128 +#define SYNC_FILE_RANGE_WAIT_BEFORE 1 +#define SYNC_FILE_RANGE_WRITE 2 +#define SYNC_FILE_RANGE_WAIT_AFTER 4 +#define SPLICE_F_MOVE 1 +#define SPLICE_F_NONBLOCK 2 +#define SPLICE_F_MORE 4 +#define SPLICE_F_GIFT 8 +int fallocate(int, int, off_t, off_t); +#define fallocate64 fallocate +int name_to_handle_at(int, const char *, struct file_handle *, int *, int); +int open_by_handle_at(int, struct file_handle *, int); +ssize_t readahead(int, off_t, size_t); +int sync_file_range(int, off_t, off_t, unsigned); +ssize_t vmsplice(int, const struct iovec *, size_t, unsigned); +ssize_t splice(int, off_t *, int, off_t *, size_t, unsigned); +ssize_t tee(int, int, size_t, unsigned); +#define loff_t off_t +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define F_GETLK64 F_GETLK +#define F_SETLK64 F_SETLK +#define F_SETLKW64 F_SETLKW +#define flock64 flock +#define open64 open +#define openat64 openat +#define creat64 creat +#define lockf64 lockf +#define posix_fadvise64 posix_fadvise +#define posix_fallocate64 posix_fallocate +#define off64_t off_t +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/features.h b/c/common/test/includes/standard-library/features.h new file mode 100644 index 0000000000..85cfb72a0d --- /dev/null +++ b/c/common/test/includes/standard-library/features.h @@ -0,0 +1,40 @@ +#ifndef _FEATURES_H +#define _FEATURES_H + +#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE 1 +#endif + +#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ + && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ + && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) +#define _BSD_SOURCE 1 +#define _XOPEN_SOURCE 700 +#endif + +#if __STDC_VERSION__ >= 199901L +#define __restrict restrict +#elif !defined(__GNUC__) +#define __restrict +#endif + +#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) +#define __inline inline +#elif !defined(__GNUC__) +#define __inline +#endif + +#if __STDC_VERSION__ >= 201112L +#elif defined(__GNUC__) +#define _Noreturn __attribute__((__noreturn__)) +#else +#define _Noreturn +#endif + +#define __REDIR(x,y) __typeof__(x) x __asm__(#y) + +#endif diff --git a/c/common/test/includes/standard-library/fenv.h b/c/common/test/includes/standard-library/fenv.h new file mode 100644 index 0000000000..05de990c0b --- /dev/null +++ b/c/common/test/includes/standard-library/fenv.h @@ -0,0 +1,28 @@ +#ifndef _FENV_H +#define _FENV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int feclearexcept(int); +int fegetexceptflag(fexcept_t *, int); +int feraiseexcept(int); +int fesetexceptflag(const fexcept_t *, int); +int fetestexcept(int); + +int fegetround(void); +int fesetround(int); + +int fegetenv(fenv_t *); +int feholdexcept(fenv_t *); +int fesetenv(const fenv_t *); +int feupdateenv(const fenv_t *); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/c/common/test/includes/standard-library/float.h b/c/common/test/includes/standard-library/float.h new file mode 100644 index 0000000000..713aadb906 --- /dev/null +++ b/c/common/test/includes/standard-library/float.h @@ -0,0 +1,52 @@ +#ifndef _FLOAT_H +#define _FLOAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +int __flt_rounds(void); +#define FLT_ROUNDS (__flt_rounds()) + +#define FLT_RADIX 2 + +#define FLT_TRUE_MIN 1.40129846432481707092e-45F +#define FLT_MIN 1.17549435082228750797e-38F +#define FLT_MAX 3.40282346638528859812e+38F +#define FLT_EPSILON 1.1920928955078125e-07F + +#define FLT_MANT_DIG 24 +#define FLT_MIN_EXP (-125) +#define FLT_MAX_EXP 128 +#define FLT_HAS_SUBNORM 1 + +#define FLT_DIG 6 +#define FLT_DECIMAL_DIG 9 +#define FLT_MIN_10_EXP (-37) +#define FLT_MAX_10_EXP 38 + +#define DBL_TRUE_MIN 4.94065645841246544177e-324 +#define DBL_MIN 2.22507385850720138309e-308 +#define DBL_MAX 1.79769313486231570815e+308 +#define DBL_EPSILON 2.22044604925031308085e-16 + +#define DBL_MANT_DIG 53 +#define DBL_MIN_EXP (-1021) +#define DBL_MAX_EXP 1024 +#define DBL_HAS_SUBNORM 1 + +#define DBL_DIG 15 +#define DBL_DECIMAL_DIG 17 +#define DBL_MIN_10_EXP (-307) +#define DBL_MAX_10_EXP 308 + +#define LDBL_HAS_SUBNORM 1 +#define LDBL_DECIMAL_DIG DECIMAL_DIG + +#include + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/fmtmsg.h b/c/common/test/includes/standard-library/fmtmsg.h new file mode 100644 index 0000000000..d944b06f8d --- /dev/null +++ b/c/common/test/includes/standard-library/fmtmsg.h @@ -0,0 +1,47 @@ +#ifndef _FMTMSG_H +#define _FMTMSG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define MM_HARD 1 +#define MM_SOFT 2 +#define MM_FIRM 4 + +#define MM_APPL 8 +#define MM_UTIL 16 +#define MM_OPSYS 32 + +#define MM_RECOVER 64 +#define MM_NRECOV 128 + +#define MM_PRINT 256 +#define MM_CONSOLE 512 + +#define MM_NULLMC 0L + +#define MM_HALT 1 +#define MM_ERROR 2 +#define MM_WARNING 3 +#define MM_INFO 4 +#define MM_NOSEV 0 + +#define MM_OK 0 +#define MM_NOTOK (-1) +#define MM_NOMSG 1 +#define MM_NOCON 4 + +#define MM_NULLLBL ((char*)0) +#define MM_NULLTXT ((char*)0) +#define MM_NULLACT ((char*)0) +#define MM_NULLTAG ((char*)0) +#define MM_NULLSEV 0 + +int fmtmsg(long, const char *, int, const char *, const char *, const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/fnmatch.h b/c/common/test/includes/standard-library/fnmatch.h new file mode 100644 index 0000000000..f9593217ff --- /dev/null +++ b/c/common/test/includes/standard-library/fnmatch.h @@ -0,0 +1,24 @@ +#ifndef _FNMATCH_H +#define _FNMATCH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define FNM_PATHNAME 0x1 +#define FNM_NOESCAPE 0x2 +#define FNM_PERIOD 0x4 +#define FNM_LEADING_DIR 0x8 +#define FNM_CASEFOLD 0x10 +#define FNM_FILE_NAME FNM_PATHNAME + +#define FNM_NOMATCH 1 +#define FNM_NOSYS (-1) + +int fnmatch(const char *, const char *, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/ftw.h b/c/common/test/includes/standard-library/ftw.h new file mode 100644 index 0000000000..b15c062a83 --- /dev/null +++ b/c/common/test/includes/standard-library/ftw.h @@ -0,0 +1,41 @@ +#ifndef _FTW_H +#define _FTW_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define FTW_F 1 +#define FTW_D 2 +#define FTW_DNR 3 +#define FTW_NS 4 +#define FTW_SL 5 +#define FTW_DP 6 +#define FTW_SLN 7 + +#define FTW_PHYS 1 +#define FTW_MOUNT 2 +#define FTW_CHDIR 4 +#define FTW_DEPTH 8 + +struct FTW { + int base; + int level; +}; + +int ftw(const char *, int (*)(const char *, const struct stat *, int), int); +int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int); + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define ftw64 ftw +#define nftw64 nftw +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/getopt.h b/c/common/test/includes/standard-library/getopt.h new file mode 100644 index 0000000000..35cbd358b5 --- /dev/null +++ b/c/common/test/includes/standard-library/getopt.h @@ -0,0 +1,30 @@ +#ifndef _GETOPT_H +#define _GETOPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +int getopt(int, char * const [], const char *); +extern char *optarg; +extern int optind, opterr, optopt, optreset; + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + +int getopt_long(int, char *const *, const char *, const struct option *, int *); +int getopt_long_only(int, char *const *, const char *, const struct option *, int *); + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/glob.h b/c/common/test/includes/standard-library/glob.h new file mode 100644 index 0000000000..4a562a206d --- /dev/null +++ b/c/common/test/includes/standard-library/glob.h @@ -0,0 +1,52 @@ +#ifndef _GLOB_H +#define _GLOB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t + +#include + +typedef struct { + size_t gl_pathc; + char **gl_pathv; + size_t gl_offs; + int __dummy1; + void *__dummy2[5]; +} glob_t; + +int glob(const char *__restrict, int, int (*)(const char *, int), glob_t *__restrict); +void globfree(glob_t *); + +#define GLOB_ERR 0x01 +#define GLOB_MARK 0x02 +#define GLOB_NOSORT 0x04 +#define GLOB_DOOFFS 0x08 +#define GLOB_NOCHECK 0x10 +#define GLOB_APPEND 0x20 +#define GLOB_NOESCAPE 0x40 +#define GLOB_PERIOD 0x80 + +#define GLOB_TILDE 0x1000 +#define GLOB_TILDE_CHECK 0x4000 + +#define GLOB_NOSPACE 1 +#define GLOB_ABORTED 2 +#define GLOB_NOMATCH 3 +#define GLOB_NOSYS 4 + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define glob64 glob +#define globfree64 globfree +#define glob64_t glob_t +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/grp.h b/c/common/test/includes/standard-library/grp.h new file mode 100644 index 0000000000..27e8c5e6c6 --- /dev/null +++ b/c/common/test/includes/standard-library/grp.h @@ -0,0 +1,53 @@ +#ifndef _GRP_H +#define _GRP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#define __NEED_gid_t + +#ifdef _GNU_SOURCE +#define __NEED_FILE +#endif + +#include + +struct group { + char *gr_name; + char *gr_passwd; + gid_t gr_gid; + char **gr_mem; +}; + +struct group *getgrgid(gid_t); +struct group *getgrnam(const char *); + +int getgrgid_r(gid_t, struct group *, char *, size_t, struct group **); +int getgrnam_r(const char *, struct group *, char *, size_t, struct group **); + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +struct group *getgrent(void); +void endgrent(void); +void setgrent(void); +#endif + +#ifdef _GNU_SOURCE +struct group *fgetgrent(FILE *); +int putgrent(const struct group *, FILE *); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int getgrouplist(const char *, gid_t, gid_t *, int *); +int setgroups(size_t, const gid_t *); +int initgroups(const char *, gid_t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/iconv.h b/c/common/test/includes/standard-library/iconv.h new file mode 100644 index 0000000000..ebe9bfda39 --- /dev/null +++ b/c/common/test/includes/standard-library/iconv.h @@ -0,0 +1,24 @@ +#ifndef _ICONV_H +#define _ICONV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t + +#include + +typedef void *iconv_t; + +iconv_t iconv_open(const char *, const char *); +size_t iconv(iconv_t, char **__restrict, size_t *__restrict, char **__restrict, size_t *__restrict); +int iconv_close(iconv_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/ifaddrs.h b/c/common/test/includes/standard-library/ifaddrs.h new file mode 100644 index 0000000000..c0328a8ea5 --- /dev/null +++ b/c/common/test/includes/standard-library/ifaddrs.h @@ -0,0 +1,35 @@ +#ifndef _IFADDRS_H +#define _IFADDRS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +struct ifaddrs { + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + union { + struct sockaddr *ifu_broadaddr; + struct sockaddr *ifu_dstaddr; + } ifa_ifu; + void *ifa_data; +}; +#define ifa_broadaddr ifa_ifu.ifu_broadaddr +#define ifa_dstaddr ifa_ifu.ifu_dstaddr + +void freeifaddrs(struct ifaddrs *); +int getifaddrs(struct ifaddrs **); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/c/common/test/includes/standard-library/inttypes.h b/c/common/test/includes/standard-library/inttypes.h new file mode 100644 index 0000000000..61dcb72731 --- /dev/null +++ b/c/common/test/includes/standard-library/inttypes.h @@ -0,0 +1,229 @@ +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define __NEED_wchar_t +#include + +typedef struct { intmax_t quot, rem; } imaxdiv_t; + +intmax_t imaxabs(intmax_t); +imaxdiv_t imaxdiv(intmax_t, intmax_t); + +intmax_t strtoimax(const char *__restrict, char **__restrict, int); +uintmax_t strtoumax(const char *__restrict, char **__restrict, int); + +intmax_t wcstoimax(const wchar_t *__restrict, wchar_t **__restrict, int); +uintmax_t wcstoumax(const wchar_t *__restrict, wchar_t **__restrict, int); + +#if UINTPTR_MAX == UINT64_MAX +#define __PRI64 "l" +#define __PRIPTR "l" +#else +#define __PRI64 "ll" +#define __PRIPTR "" +#endif + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64 "d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 __PRI64 "d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 "d" +#define PRIdFAST32 "d" +#define PRIdFAST64 __PRI64 "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64 "i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 __PRI64 "i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 "i" +#define PRIiFAST32 "i" +#define PRIiFAST64 __PRI64 "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64 "o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 __PRI64 "o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 "o" +#define PRIoFAST32 "o" +#define PRIoFAST64 __PRI64 "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64 "u" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 __PRI64 "u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 "u" +#define PRIuFAST32 "u" +#define PRIuFAST64 __PRI64 "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64 "x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 __PRI64 "x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 "x" +#define PRIxFAST32 "x" +#define PRIxFAST64 __PRI64 "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64 "X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 __PRI64 "X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 "X" +#define PRIXFAST32 "X" +#define PRIXFAST64 __PRI64 "X" + +#define PRIdMAX __PRI64 "d" +#define PRIiMAX __PRI64 "i" +#define PRIoMAX __PRI64 "o" +#define PRIuMAX __PRI64 "u" +#define PRIxMAX __PRI64 "x" +#define PRIXMAX __PRI64 "X" + +#define PRIdPTR __PRIPTR "d" +#define PRIiPTR __PRIPTR "i" +#define PRIoPTR __PRIPTR "o" +#define PRIuPTR __PRIPTR "u" +#define PRIxPTR __PRIPTR "x" +#define PRIXPTR __PRIPTR "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 __PRI64 "d" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 __PRI64 "d" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 "d" +#define SCNdFAST32 "d" +#define SCNdFAST64 __PRI64 "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 __PRI64 "i" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 __PRI64 "i" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 "i" +#define SCNiFAST32 "i" +#define SCNiFAST64 __PRI64 "i" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 __PRI64 "u" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 __PRI64 "u" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 "u" +#define SCNuFAST32 "u" +#define SCNuFAST64 __PRI64 "u" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 __PRI64 "o" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 __PRI64 "o" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 "o" +#define SCNoFAST32 "o" +#define SCNoFAST64 __PRI64 "o" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 __PRI64 "x" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 __PRI64 "x" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 "x" +#define SCNxFAST32 "x" +#define SCNxFAST64 __PRI64 "x" + +#define SCNdMAX __PRI64 "d" +#define SCNiMAX __PRI64 "i" +#define SCNoMAX __PRI64 "o" +#define SCNuMAX __PRI64 "u" +#define SCNxMAX __PRI64 "x" + +#define SCNdPTR __PRIPTR "d" +#define SCNiPTR __PRIPTR "i" +#define SCNoPTR __PRIPTR "o" +#define SCNuPTR __PRIPTR "u" +#define SCNxPTR __PRIPTR "x" + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/c/common/test/includes/standard-library/iso646.h b/c/common/test/includes/standard-library/iso646.h new file mode 100644 index 0000000000..88ff53d7b8 --- /dev/null +++ b/c/common/test/includes/standard-library/iso646.h @@ -0,0 +1,20 @@ +#ifndef _ISO646_H +#define _ISO646_H + +#ifndef __cplusplus + +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= + +#endif + +#endif diff --git a/c/common/test/includes/standard-library/langinfo.h b/c/common/test/includes/standard-library/langinfo.h new file mode 100644 index 0000000000..519c061294 --- /dev/null +++ b/c/common/test/includes/standard-library/langinfo.h @@ -0,0 +1,98 @@ +#ifndef _LANGINFO_H +#define _LANGINFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define __NEED_locale_t + +#include + +#define ABDAY_1 0x20000 +#define ABDAY_2 0x20001 +#define ABDAY_3 0x20002 +#define ABDAY_4 0x20003 +#define ABDAY_5 0x20004 +#define ABDAY_6 0x20005 +#define ABDAY_7 0x20006 + +#define DAY_1 0x20007 +#define DAY_2 0x20008 +#define DAY_3 0x20009 +#define DAY_4 0x2000A +#define DAY_5 0x2000B +#define DAY_6 0x2000C +#define DAY_7 0x2000D + +#define ABMON_1 0x2000E +#define ABMON_2 0x2000F +#define ABMON_3 0x20010 +#define ABMON_4 0x20011 +#define ABMON_5 0x20012 +#define ABMON_6 0x20013 +#define ABMON_7 0x20014 +#define ABMON_8 0x20015 +#define ABMON_9 0x20016 +#define ABMON_10 0x20017 +#define ABMON_11 0x20018 +#define ABMON_12 0x20019 + +#define MON_1 0x2001A +#define MON_2 0x2001B +#define MON_3 0x2001C +#define MON_4 0x2001D +#define MON_5 0x2001E +#define MON_6 0x2001F +#define MON_7 0x20020 +#define MON_8 0x20021 +#define MON_9 0x20022 +#define MON_10 0x20023 +#define MON_11 0x20024 +#define MON_12 0x20025 + +#define AM_STR 0x20026 +#define PM_STR 0x20027 + +#define D_T_FMT 0x20028 +#define D_FMT 0x20029 +#define T_FMT 0x2002A +#define T_FMT_AMPM 0x2002B + +#define ERA 0x2002C +#define ERA_D_FMT 0x2002E +#define ALT_DIGITS 0x2002F +#define ERA_D_T_FMT 0x20030 +#define ERA_T_FMT 0x20031 + +#define CODESET 14 + +#define CRNCYSTR 0x4000F + +#define RADIXCHAR 0x10000 +#define THOUSEP 0x10001 +#define YESEXPR 0x50000 +#define NOEXPR 0x50001 + +#define _NL_LOCALE_NAME(cat) (((cat)<<16) | 0xffff) + +#if defined(_GNU_SOURCE) +#define NL_LOCALE_NAME(cat) _NL_LOCALE_NAME(cat) +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define YESSTR 0x50002 +#define NOSTR 0x50003 +#endif + +char *nl_langinfo(nl_item); +char *nl_langinfo_l(nl_item, locale_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/lastlog.h b/c/common/test/includes/standard-library/lastlog.h new file mode 100644 index 0000000000..5fa45ee477 --- /dev/null +++ b/c/common/test/includes/standard-library/lastlog.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/libgen.h b/c/common/test/includes/standard-library/libgen.h new file mode 100644 index 0000000000..7c7fd9c6d2 --- /dev/null +++ b/c/common/test/includes/standard-library/libgen.h @@ -0,0 +1,15 @@ +#ifndef _LIBGEN_H +#define _LIBGEN_H + +#ifdef __cplusplus +extern "C" { +#endif + +char *dirname(char *); +char *basename(char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/libintl.h b/c/common/test/includes/standard-library/libintl.h new file mode 100644 index 0000000000..6a707bf0f0 --- /dev/null +++ b/c/common/test/includes/standard-library/libintl.h @@ -0,0 +1,33 @@ +#ifndef _LIBINTL_H +#define _LIBINTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __USE_GNU_GETTEXT 1 +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 1 : -1) + +#if __GNUC__ >= 3 +#define __fa(n) __attribute__ ((__format_arg__ (n))) +#else +#define __fa(n) +#endif + +char *gettext(const char *) __fa(1); +char *dgettext(const char *, const char *) __fa(2); +char *dcgettext(const char *, const char *, int) __fa(2); +char *ngettext(const char *, const char *, unsigned long) __fa(1) __fa(2); +char *dngettext(const char *, const char *, const char *, unsigned long) __fa(2) __fa(3); +char *dcngettext(const char *, const char *, const char *, unsigned long, int) __fa(2) __fa(3); +char *textdomain(const char *); +char *bindtextdomain (const char *, const char *); +char *bind_textdomain_codeset(const char *, const char *); + +#undef __fa + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/limits.h b/c/common/test/includes/standard-library/limits.h new file mode 100644 index 0000000000..53a27b9de4 --- /dev/null +++ b/c/common/test/includes/standard-library/limits.h @@ -0,0 +1,166 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +#include + +#include /* __LONG_MAX */ + +/* Support signed or unsigned plain-char */ + +#if '\xff' > 0 +#define CHAR_MIN 0 +#define CHAR_MAX 255 +#else +#define CHAR_MIN (-128) +#define CHAR_MAX 127 +#endif + +#define CHAR_BIT 8 +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 +#define SHRT_MIN (-1-0x7fff) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff +#define INT_MIN (-1-0x7fffffff) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffffU +#define LONG_MIN (-LONG_MAX-1) +#define LONG_MAX __LONG_MAX +#define ULONG_MAX (2UL*LONG_MAX+1) +#define LLONG_MIN (-LLONG_MAX-1) +#define LLONG_MAX 0x7fffffffffffffffLL +#define ULLONG_MAX (2ULL*LLONG_MAX+1) + +#define MB_LEN_MAX 4 + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +#include + +#define PIPE_BUF 4096 +#define FILESIZEBITS 64 +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif +#define PATH_MAX 4096 +#define NGROUPS_MAX 32 +#define ARG_MAX 131072 +#define IOV_MAX 1024 +#define SYMLOOP_MAX 40 +#define WORD_BIT 32 +#define SSIZE_MAX LONG_MAX +#define TZNAME_MAX 6 +#define TTY_NAME_MAX 32 +#define HOST_NAME_MAX 255 + +#if LONG_MAX == 0x7fffffffL +#define LONG_BIT 32 +#else +#define LONG_BIT 64 +#endif + +/* Implementation choices... */ + +#define PTHREAD_KEYS_MAX 128 +#define PTHREAD_STACK_MIN 2048 +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 +#define SEM_VALUE_MAX 0x7fffffff +#define SEM_NSEMS_MAX 256 +#define DELAYTIMER_MAX 0x7fffffff +#define MQ_PRIO_MAX 32768 +#define LOGIN_NAME_MAX 256 + +/* Arbitrary numbers... */ + +#define BC_BASE_MAX 99 +#define BC_DIM_MAX 2048 +#define BC_SCALE_MAX 99 +#define BC_STRING_MAX 1000 +#define CHARCLASS_NAME_MAX 14 +#define COLL_WEIGHTS_MAX 2 +#define EXPR_NEST_MAX 32 +#define LINE_MAX 4096 +#define RE_DUP_MAX 255 + +#define NL_ARGMAX 9 +#define NL_MSGMAX 32767 +#define NL_SETMAX 255 +#define NL_TEXTMAX 2048 + +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + +#ifdef PAGESIZE +#define PAGE_SIZE PAGESIZE +#endif +#define NZERO 20 +#define NL_LANGMAX 32 + +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) + +#define NL_NMAX 16 + +#endif + +/* POSIX/SUS requirements follow. These numbers come directly + * from SUS and have nothing to do with the host system. */ + +#define _POSIX_AIO_LISTIO_MAX 2 +#define _POSIX_AIO_MAX 1 +#define _POSIX_ARG_MAX 4096 +#define _POSIX_CHILD_MAX 25 +#define _POSIX_CLOCKRES_MIN 20000000 +#define _POSIX_DELAYTIMER_MAX 32 +#define _POSIX_HOST_NAME_MAX 255 +#define _POSIX_LINK_MAX 8 +#define _POSIX_LOGIN_NAME_MAX 9 +#define _POSIX_MAX_CANON 255 +#define _POSIX_MAX_INPUT 255 +#define _POSIX_MQ_OPEN_MAX 8 +#define _POSIX_MQ_PRIO_MAX 32 +#define _POSIX_NAME_MAX 14 +#define _POSIX_NGROUPS_MAX 8 +#define _POSIX_OPEN_MAX 20 +#define _POSIX_PATH_MAX 256 +#define _POSIX_PIPE_BUF 512 +#define _POSIX_RE_DUP_MAX 255 +#define _POSIX_RTSIG_MAX 8 +#define _POSIX_SEM_NSEMS_MAX 256 +#define _POSIX_SEM_VALUE_MAX 32767 +#define _POSIX_SIGQUEUE_MAX 32 +#define _POSIX_SSIZE_MAX 32767 +#define _POSIX_STREAM_MAX 8 +#define _POSIX_SS_REPL_MAX 4 +#define _POSIX_SYMLINK_MAX 255 +#define _POSIX_SYMLOOP_MAX 8 +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +#define _POSIX_THREAD_KEYS_MAX 128 +#define _POSIX_THREAD_THREADS_MAX 64 +#define _POSIX_TIMER_MAX 32 +#define _POSIX_TRACE_EVENT_NAME_MAX 30 +#define _POSIX_TRACE_NAME_MAX 8 +#define _POSIX_TRACE_SYS_MAX 8 +#define _POSIX_TRACE_USER_EVENT_MAX 32 +#define _POSIX_TTY_NAME_MAX 9 +#define _POSIX_TZNAME_MAX 6 +#define _POSIX2_BC_BASE_MAX 99 +#define _POSIX2_BC_DIM_MAX 2048 +#define _POSIX2_BC_SCALE_MAX 99 +#define _POSIX2_BC_STRING_MAX 1000 +#define _POSIX2_CHARCLASS_NAME_MAX 14 +#define _POSIX2_COLL_WEIGHTS_MAX 2 +#define _POSIX2_EXPR_NEST_MAX 32 +#define _POSIX2_LINE_MAX 2048 +#define _POSIX2_RE_DUP_MAX 255 + +#define _XOPEN_IOV_MAX 16 +#define _XOPEN_NAME_MAX 255 +#define _XOPEN_PATH_MAX 1024 + +#endif diff --git a/c/common/test/includes/standard-library/link.h b/c/common/test/includes/standard-library/link.h new file mode 100644 index 0000000000..815018594c --- /dev/null +++ b/c/common/test/includes/standard-library/link.h @@ -0,0 +1,53 @@ +#ifndef _LINK_H +#define _LINK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#define __NEED_size_t +#define __NEED_uint32_t +#include + +#if UINTPTR_MAX > 0xffffffff +#define ElfW(type) Elf64_ ## type +#else +#define ElfW(type) Elf32_ ## type +#endif + +#include + +struct dl_phdr_info { + ElfW(Addr) dlpi_addr; + const char *dlpi_name; + const ElfW(Phdr) *dlpi_phdr; + ElfW(Half) dlpi_phnum; + unsigned long long int dlpi_adds; + unsigned long long int dlpi_subs; + size_t dlpi_tls_modid; + void *dlpi_tls_data; +}; + +struct link_map { + ElfW(Addr) l_addr; + char *l_name; + ElfW(Dyn) *l_ld; + struct link_map *l_next, *l_prev; +}; + +struct r_debug { + int r_version; + struct link_map *r_map; + ElfW(Addr) r_brk; + enum { RT_CONSISTENT, RT_ADD, RT_DELETE } r_state; + ElfW(Addr) r_ldbase; +}; + +int dl_iterate_phdr(int (*)(struct dl_phdr_info *, size_t, void *), void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/locale.h b/c/common/test/includes/standard-library/locale.h new file mode 100644 index 0000000000..ce384381c6 --- /dev/null +++ b/c/common/test/includes/standard-library/locale.h @@ -0,0 +1,86 @@ +#ifndef _LOCALE_H +#define _LOCALE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#define LC_CTYPE 0 +#define LC_NUMERIC 1 +#define LC_TIME 2 +#define LC_COLLATE 3 +#define LC_MONETARY 4 +#define LC_MESSAGES 5 +#define LC_ALL 6 + +struct lconv { + char *decimal_point; + char *thousands_sep; + char *grouping; + + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + char int_p_cs_precedes; + char int_p_sep_by_space; + char int_n_cs_precedes; + char int_n_sep_by_space; + char int_p_sign_posn; + char int_n_sign_posn; +}; + + +char *setlocale (int, const char *); +struct lconv *localeconv(void); + + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +#define __NEED_locale_t + +#include + +#define LC_GLOBAL_LOCALE ((locale_t)-1) + +#define LC_CTYPE_MASK (1< + +void *malloc (size_t); +void *calloc (size_t, size_t); +void *realloc (void *, size_t); +void free (void *); +void *valloc (size_t); +void *memalign(size_t, size_t); + +size_t malloc_usable_size(void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/math.h b/c/common/test/includes/standard-library/math.h new file mode 100644 index 0000000000..14f28ec8c6 --- /dev/null +++ b/c/common/test/includes/standard-library/math.h @@ -0,0 +1,442 @@ +#ifndef _MATH_H +#define _MATH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_float_t +#define __NEED_double_t +#include + +#if 100*__GNUC__+__GNUC_MINOR__ >= 303 +#define NAN __builtin_nanf("") +#define INFINITY __builtin_inff() +#else +#define NAN (0.0f/0.0f) +#define INFINITY 1e5000f +#endif + +#define HUGE_VALF INFINITY +#define HUGE_VAL ((double)INFINITY) +#define HUGE_VALL ((long double)INFINITY) + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 +#define math_errhandling 2 + +#define FP_ILOGBNAN (-1-0x7fffffff) +#define FP_ILOGB0 FP_ILOGBNAN + +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 + +#ifdef __FP_FAST_FMA +#define FP_FAST_FMA 1 +#endif + +#ifdef __FP_FAST_FMAF +#define FP_FAST_FMAF 1 +#endif + +#ifdef __FP_FAST_FMAL +#define FP_FAST_FMAL 1 +#endif + +int __fpclassify(double); +int __fpclassifyf(float); +int __fpclassifyl(long double); + +static __inline unsigned __FLOAT_BITS(float __f) +{ + union {float __f; unsigned __i;} __u; + __u.__f = __f; + return __u.__i; +} +static __inline unsigned long long __DOUBLE_BITS(double __f) +{ + union {double __f; unsigned long long __i;} __u; + __u.__f = __f; + return __u.__i; +} + +#define fpclassify(x) ( \ + sizeof(x) == sizeof(float) ? __fpclassifyf(x) : \ + sizeof(x) == sizeof(double) ? __fpclassify(x) : \ + __fpclassifyl(x) ) + +#define isinf(x) ( \ + sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) == 0x7f800000 : \ + sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) == 0x7ffULL<<52 : \ + __fpclassifyl(x) == FP_INFINITE) + +#define isnan(x) ( \ + sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) > 0x7f800000 : \ + sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) > 0x7ffULL<<52 : \ + __fpclassifyl(x) == FP_NAN) + +#define isnormal(x) ( \ + sizeof(x) == sizeof(float) ? ((__FLOAT_BITS(x)+0x00800000) & 0x7fffffff) >= 0x01000000 : \ + sizeof(x) == sizeof(double) ? ((__DOUBLE_BITS(x)+(1ULL<<52)) & -1ULL>>1) >= 1ULL<<53 : \ + __fpclassifyl(x) == FP_NORMAL) + +#define isfinite(x) ( \ + sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) < 0x7f800000 : \ + sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) < 0x7ffULL<<52 : \ + __fpclassifyl(x) > FP_INFINITE) + +int __signbit(double); +int __signbitf(float); +int __signbitl(long double); + +#define signbit(x) ( \ + sizeof(x) == sizeof(float) ? (int)(__FLOAT_BITS(x)>>31) : \ + sizeof(x) == sizeof(double) ? (int)(__DOUBLE_BITS(x)>>63) : \ + __signbitl(x) ) + +#define isunordered(x,y) (isnan((x)) ? ((void)(y),1) : isnan((y))) + +#define __ISREL_DEF(rel, op, type) \ +static __inline int __is##rel(type __x, type __y) \ +{ return !isunordered(__x,__y) && __x op __y; } + +__ISREL_DEF(lessf, <, float_t) +__ISREL_DEF(less, <, double_t) +__ISREL_DEF(lessl, <, long double) +__ISREL_DEF(lessequalf, <=, float_t) +__ISREL_DEF(lessequal, <=, double_t) +__ISREL_DEF(lessequall, <=, long double) +__ISREL_DEF(lessgreaterf, !=, float_t) +__ISREL_DEF(lessgreater, !=, double_t) +__ISREL_DEF(lessgreaterl, !=, long double) +__ISREL_DEF(greaterf, >, float_t) +__ISREL_DEF(greater, >, double_t) +__ISREL_DEF(greaterl, >, long double) +__ISREL_DEF(greaterequalf, >=, float_t) +__ISREL_DEF(greaterequal, >=, double_t) +__ISREL_DEF(greaterequall, >=, long double) + +#define __tg_pred_2(x, y, p) ( \ + sizeof((x)+(y)) == sizeof(float) ? p##f(x, y) : \ + sizeof((x)+(y)) == sizeof(double) ? p(x, y) : \ + p##l(x, y) ) + +#define isless(x, y) __tg_pred_2(x, y, __isless) +#define islessequal(x, y) __tg_pred_2(x, y, __islessequal) +#define islessgreater(x, y) __tg_pred_2(x, y, __islessgreater) +#define isgreater(x, y) __tg_pred_2(x, y, __isgreater) +#define isgreaterequal(x, y) __tg_pred_2(x, y, __isgreaterequal) + +double acos(double); +float acosf(float); +long double acosl(long double); + +double acosh(double); +float acoshf(float); +long double acoshl(long double); + +double asin(double); +float asinf(float); +long double asinl(long double); + +double asinh(double); +float asinhf(float); +long double asinhl(long double); + +double atan(double); +float atanf(float); +long double atanl(long double); + +double atan2(double, double); +float atan2f(float, float); +long double atan2l(long double, long double); + +double atanh(double); +float atanhf(float); +long double atanhl(long double); + +double cbrt(double); +float cbrtf(float); +long double cbrtl(long double); + +double ceil(double); +float ceilf(float); +long double ceill(long double); + +double copysign(double, double); +float copysignf(float, float); +long double copysignl(long double, long double); + +double cos(double); +float cosf(float); +long double cosl(long double); + +double cosh(double); +float coshf(float); +long double coshl(long double); + +double erf(double); +float erff(float); +long double erfl(long double); + +double erfc(double); +float erfcf(float); +long double erfcl(long double); + +double exp(double); +float expf(float); +long double expl(long double); + +double exp2(double); +float exp2f(float); +long double exp2l(long double); + +double expm1(double); +float expm1f(float); +long double expm1l(long double); + +double fabs(double); +float fabsf(float); +long double fabsl(long double); + +double fdim(double, double); +float fdimf(float, float); +long double fdiml(long double, long double); + +double floor(double); +float floorf(float); +long double floorl(long double); + +double fma(double, double, double); +float fmaf(float, float, float); +long double fmal(long double, long double, long double); + +double fmax(double, double); +float fmaxf(float, float); +long double fmaxl(long double, long double); + +double fmin(double, double); +float fminf(float, float); +long double fminl(long double, long double); + +double fmod(double, double); +float fmodf(float, float); +long double fmodl(long double, long double); + +double frexp(double, int *); +float frexpf(float, int *); +long double frexpl(long double, int *); + +double hypot(double, double); +float hypotf(float, float); +long double hypotl(long double, long double); + +int ilogb(double); +int ilogbf(float); +int ilogbl(long double); + +double ldexp(double, int); +float ldexpf(float, int); +long double ldexpl(long double, int); + +double lgamma(double); +float lgammaf(float); +long double lgammal(long double); + +long long llrint(double); +long long llrintf(float); +long long llrintl(long double); + +long long llround(double); +long long llroundf(float); +long long llroundl(long double); + +double log(double); +float logf(float); +long double logl(long double); + +double log10(double); +float log10f(float); +long double log10l(long double); + +double log1p(double); +float log1pf(float); +long double log1pl(long double); + +double log2(double); +float log2f(float); +long double log2l(long double); + +double logb(double); +float logbf(float); +long double logbl(long double); + +long lrint(double); +long lrintf(float); +long lrintl(long double); + +long lround(double); +long lroundf(float); +long lroundl(long double); + +double modf(double, double *); +float modff(float, float *); +long double modfl(long double, long double *); + +double nan(const char *); +float nanf(const char *); +long double nanl(const char *); + +double nearbyint(double); +float nearbyintf(float); +long double nearbyintl(long double); + +double nextafter(double, double); +float nextafterf(float, float); +long double nextafterl(long double, long double); + +double nexttoward(double, long double); +float nexttowardf(float, long double); +long double nexttowardl(long double, long double); + +double pow(double, double); +float powf(float, float); +long double powl(long double, long double); + +double remainder(double, double); +float remainderf(float, float); +long double remainderl(long double, long double); + +double remquo(double, double, int *); +float remquof(float, float, int *); +long double remquol(long double, long double, int *); + +double rint(double); +float rintf(float); +long double rintl(long double); + +double round(double); +float roundf(float); +long double roundl(long double); + +double scalbln(double, long); +float scalblnf(float, long); +long double scalblnl(long double, long); + +double scalbn(double, int); +float scalbnf(float, int); +long double scalbnl(long double, int); + +double sin(double); +float sinf(float); +long double sinl(long double); + +double sinh(double); +float sinhf(float); +long double sinhl(long double); + +double sqrt(double); +float sqrtf(float); +long double sqrtl(long double); + +double tan(double); +float tanf(float); +long double tanl(long double); + +double tanh(double); +float tanhf(float); +long double tanhl(long double); + +double tgamma(double); +float tgammaf(float); +long double tgammal(long double); + +double trunc(double); +float truncf(float); +long double truncl(long double); + + +#if defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) +#undef MAXFLOAT +#define MAXFLOAT 3.40282346638528859812e+38F +#endif + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define M_E 2.7182818284590452354 /* e */ +#define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#define M_PI 3.14159265358979323846 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +extern int signgam; + +double j0(double); +double j1(double); +double jn(int, double); + +double y0(double); +double y1(double); +double yn(int, double); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define HUGE 3.40282346638528859812e+38F + +double drem(double, double); +float dremf(float, float); + +int finite(double); +int finitef(float); + +double scalb(double, double); +float scalbf(float, float); + +double significand(double); +float significandf(float); + +double lgamma_r(double, int*); +float lgammaf_r(float, int*); + +float j0f(float); +float j1f(float); +float jnf(int, float); + +float y0f(float); +float y1f(float); +float ynf(int, float); +#endif + +#ifdef _GNU_SOURCE +long double lgammal_r(long double, int*); + +void sincos(double, double*, double*); +void sincosf(float, float*, float*); +void sincosl(long double, long double*, long double*); + +double exp10(double); +float exp10f(float); +long double exp10l(long double); + +double pow10(double); +float pow10f(float); +long double pow10l(long double); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/memory.h b/c/common/test/includes/standard-library/memory.h new file mode 100644 index 0000000000..3b2f590027 --- /dev/null +++ b/c/common/test/includes/standard-library/memory.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/mntent.h b/c/common/test/includes/standard-library/mntent.h new file mode 100644 index 0000000000..3492a1d6da --- /dev/null +++ b/c/common/test/includes/standard-library/mntent.h @@ -0,0 +1,43 @@ +#ifndef _MNTENT_H +#define _MNTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_FILE +#include + +#define MOUNTED "/etc/mtab" + +#define MNTTYPE_IGNORE "ignore" +#define MNTTYPE_NFS "nfs" +#define MNTTYPE_SWAP "swap" +#define MNTOPT_DEFAULTS "defaults" +#define MNTOPT_RO "ro" +#define MNTOPT_RW "rw" +#define MNTOPT_SUID "suid" +#define MNTOPT_NOSUID "nosuid" +#define MNTOPT_NOAUTO "noauto" + +struct mntent { + char *mnt_fsname; + char *mnt_dir; + char *mnt_type; + char *mnt_opts; + int mnt_freq; + int mnt_passno; +}; + +FILE *setmntent(const char *, const char *); +int endmntent(FILE *); +struct mntent *getmntent(FILE *); +struct mntent *getmntent_r(FILE *, struct mntent *, char *, int); +int addmntent(FILE *, const struct mntent *); +char *hasmntopt(const struct mntent *, const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/monetary.h b/c/common/test/includes/standard-library/monetary.h new file mode 100644 index 0000000000..a91fa56557 --- /dev/null +++ b/c/common/test/includes/standard-library/monetary.h @@ -0,0 +1,23 @@ +#ifndef _MONETARY_H +#define _MONETARY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_ssize_t +#define __NEED_size_t +#define __NEED_locale_t + +#include + +ssize_t strfmon(char *__restrict, size_t, const char *__restrict, ...); +ssize_t strfmon_l(char *__restrict, size_t, locale_t, const char *__restrict, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/mqueue.h b/c/common/test/includes/standard-library/mqueue.h new file mode 100644 index 0000000000..0c807ea0cb --- /dev/null +++ b/c/common/test/includes/standard-library/mqueue.h @@ -0,0 +1,41 @@ +#ifndef _MQUEUE_H +#define _MQUEUE_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#define __NEED_ssize_t +#define __NEED_pthread_attr_t +#define __NEED_time_t +#define __NEED_struct_timespec +#include + +typedef int mqd_t; +struct mq_attr { + long mq_flags, mq_maxmsg, mq_msgsize, mq_curmsgs, __unused[4]; +}; +struct sigevent; + +int mq_close(mqd_t); +int mq_getattr(mqd_t, struct mq_attr *); +int mq_notify(mqd_t, const struct sigevent *); +mqd_t mq_open(const char *, int, ...); +ssize_t mq_receive(mqd_t, char *, size_t, unsigned *); +int mq_send(mqd_t, const char *, size_t, unsigned); +int mq_setattr(mqd_t, const struct mq_attr *__restrict, struct mq_attr *__restrict); +ssize_t mq_timedreceive(mqd_t, char *__restrict, size_t, unsigned *__restrict, const struct timespec *__restrict); +int mq_timedsend(mqd_t, const char *, size_t, unsigned, const struct timespec *); +int mq_unlink(const char *); + +#if _REDIR_TIME64 +__REDIR(mq_timedreceive, __mq_timedreceive_time64); +__REDIR(mq_timedsend, __mq_timedsend_time64); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/net/ethernet.h b/c/common/test/includes/standard-library/net/ethernet.h new file mode 100644 index 0000000000..c8d4177fd2 --- /dev/null +++ b/c/common/test/includes/standard-library/net/ethernet.h @@ -0,0 +1,55 @@ +#ifndef _NET_ETHERNET_H +#define _NET_ETHERNET_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +struct ether_addr { + uint8_t ether_addr_octet[ETH_ALEN]; +}; + +struct ether_header { + uint8_t ether_dhost[ETH_ALEN]; + uint8_t ether_shost[ETH_ALEN]; + uint16_t ether_type; +}; + +#define ETHERTYPE_PUP 0x0200 +#define ETHERTYPE_SPRITE 0x0500 +#define ETHERTYPE_IP 0x0800 +#define ETHERTYPE_ARP 0x0806 +#define ETHERTYPE_REVARP 0x8035 +#define ETHERTYPE_AT 0x809B +#define ETHERTYPE_AARP 0x80F3 +#define ETHERTYPE_VLAN 0x8100 +#define ETHERTYPE_IPX 0x8137 +#define ETHERTYPE_IPV6 0x86dd +#define ETHERTYPE_LOOPBACK 0x9000 + + +#define ETHER_ADDR_LEN ETH_ALEN +#define ETHER_TYPE_LEN 2 +#define ETHER_CRC_LEN 4 +#define ETHER_HDR_LEN ETH_HLEN +#define ETHER_MIN_LEN (ETH_ZLEN + ETHER_CRC_LEN) +#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETHER_CRC_LEN) + +#define ETHER_IS_VALID_LEN(foo) \ + ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) + +#define ETHERTYPE_TRAIL 0x1000 +#define ETHERTYPE_NTRAILER 16 + +#define ETHERMTU ETH_DATA_LEN +#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/net/if.h b/c/common/test/includes/standard-library/net/if.h new file mode 100644 index 0000000000..774cbff0b5 --- /dev/null +++ b/c/common/test/includes/standard-library/net/if.h @@ -0,0 +1,141 @@ +#ifndef _NET_IF_H +#define _NET_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define IF_NAMESIZE 16 + +struct if_nameindex { + unsigned int if_index; + char *if_name; +}; + +unsigned int if_nametoindex (const char *); +char *if_indextoname (unsigned int, char *); +struct if_nameindex *if_nameindex (void); +void if_freenameindex (struct if_nameindex *); + + + + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +#include + +#define IFF_UP 0x1 +#define IFF_BROADCAST 0x2 +#define IFF_DEBUG 0x4 +#define IFF_LOOPBACK 0x8 +#define IFF_POINTOPOINT 0x10 +#define IFF_NOTRAILERS 0x20 +#define IFF_RUNNING 0x40 +#define IFF_NOARP 0x80 +#define IFF_PROMISC 0x100 +#define IFF_ALLMULTI 0x200 +#define IFF_MASTER 0x400 +#define IFF_SLAVE 0x800 +#define IFF_MULTICAST 0x1000 +#define IFF_PORTSEL 0x2000 +#define IFF_AUTOMEDIA 0x4000 +#define IFF_DYNAMIC 0x8000 +#define IFF_LOWER_UP 0x10000 +#define IFF_DORMANT 0x20000 +#define IFF_ECHO 0x40000 +#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST| \ + IFF_ECHO|IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT) + +struct ifaddr { + struct sockaddr ifa_addr; + union { + struct sockaddr ifu_broadaddr; + struct sockaddr ifu_dstaddr; + } ifa_ifu; + struct iface *ifa_ifp; + struct ifaddr *ifa_next; +}; + +#define ifa_broadaddr ifa_ifu.ifu_broadaddr +#define ifa_dstaddr ifa_ifu.ifu_dstaddr + +struct ifmap { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned short int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +#define IFHWADDRLEN 6 +#define IFNAMSIZ IF_NAMESIZE + +struct ifreq { + union { + char ifrn_name[IFNAMSIZ]; + } ifr_ifrn; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short int ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; + char ifru_newname[IFNAMSIZ]; + char *ifru_data; + } ifr_ifru; +}; + +#define ifr_name ifr_ifrn.ifrn_name +#define ifr_hwaddr ifr_ifru.ifru_hwaddr +#define ifr_addr ifr_ifru.ifru_addr +#define ifr_dstaddr ifr_ifru.ifru_dstaddr +#define ifr_broadaddr ifr_ifru.ifru_broadaddr +#define ifr_netmask ifr_ifru.ifru_netmask +#define ifr_flags ifr_ifru.ifru_flags +#define ifr_metric ifr_ifru.ifru_ivalue +#define ifr_mtu ifr_ifru.ifru_mtu +#define ifr_map ifr_ifru.ifru_map +#define ifr_slave ifr_ifru.ifru_slave +#define ifr_data ifr_ifru.ifru_data +#define ifr_ifindex ifr_ifru.ifru_ivalue +#define ifr_bandwidth ifr_ifru.ifru_ivalue +#define ifr_qlen ifr_ifru.ifru_ivalue +#define ifr_newname ifr_ifru.ifru_newname +#define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0) +#define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0) +#define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0) + +struct ifconf { + int ifc_len; + union { + char *ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; +}; + +#define ifc_buf ifc_ifcu.ifcu_buf +#define ifc_req ifc_ifcu.ifcu_req +#define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) + +#define __UAPI_DEF_IF_IFCONF 0 +#define __UAPI_DEF_IF_IFMAP 0 +#define __UAPI_DEF_IF_IFNAMSIZ 0 +#define __UAPI_DEF_IF_IFREQ 0 +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0 +#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 0 + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/net/if_arp.h b/c/common/test/includes/standard-library/net/if_arp.h new file mode 100644 index 0000000000..27becc835e --- /dev/null +++ b/c/common/test/includes/standard-library/net/if_arp.h @@ -0,0 +1,142 @@ +/* Nonstandard header */ +#ifndef _NET_IF_ARP_H +#define _NET_IF_ARP_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define MAX_ADDR_LEN 7 + +#define ARPOP_REQUEST 1 +#define ARPOP_REPLY 2 +#define ARPOP_RREQUEST 3 +#define ARPOP_RREPLY 4 +#define ARPOP_InREQUEST 8 +#define ARPOP_InREPLY 9 +#define ARPOP_NAK 10 + +struct arphdr { + uint16_t ar_hrd; + uint16_t ar_pro; + uint8_t ar_hln; + uint8_t ar_pln; + uint16_t ar_op; +}; + + +#define ARPHRD_NETROM 0 +#define ARPHRD_ETHER 1 +#define ARPHRD_EETHER 2 +#define ARPHRD_AX25 3 +#define ARPHRD_PRONET 4 +#define ARPHRD_CHAOS 5 +#define ARPHRD_IEEE802 6 +#define ARPHRD_ARCNET 7 +#define ARPHRD_APPLETLK 8 +#define ARPHRD_DLCI 15 +#define ARPHRD_ATM 19 +#define ARPHRD_METRICOM 23 +#define ARPHRD_IEEE1394 24 +#define ARPHRD_EUI64 27 +#define ARPHRD_INFINIBAND 32 +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 +#define ARPHRD_HWX25 272 +#define ARPHRD_CAN 280 +#define ARPHRD_PPP 512 +#define ARPHRD_CISCO 513 +#define ARPHRD_HDLC ARPHRD_CISCO +#define ARPHRD_LAPB 516 +#define ARPHRD_DDCMP 517 +#define ARPHRD_RAWHDLC 518 +#define ARPHRD_RAWIP 519 + +#define ARPHRD_TUNNEL 768 +#define ARPHRD_TUNNEL6 769 +#define ARPHRD_FRAD 770 +#define ARPHRD_SKIP 771 +#define ARPHRD_LOOPBACK 772 +#define ARPHRD_LOCALTLK 773 +#define ARPHRD_FDDI 774 +#define ARPHRD_BIF 775 +#define ARPHRD_SIT 776 +#define ARPHRD_IPDDP 777 +#define ARPHRD_IPGRE 778 +#define ARPHRD_PIMREG 779 +#define ARPHRD_HIPPI 780 +#define ARPHRD_ASH 781 +#define ARPHRD_ECONET 782 +#define ARPHRD_IRDA 783 +#define ARPHRD_FCPP 784 +#define ARPHRD_FCAL 785 +#define ARPHRD_FCPL 786 +#define ARPHRD_FCFABRIC 787 +#define ARPHRD_IEEE802_TR 800 +#define ARPHRD_IEEE80211 801 +#define ARPHRD_IEEE80211_PRISM 802 +#define ARPHRD_IEEE80211_RADIOTAP 803 +#define ARPHRD_IEEE802154 804 +#define ARPHRD_IEEE802154_MONITOR 805 +#define ARPHRD_PHONET 820 +#define ARPHRD_PHONET_PIPE 821 +#define ARPHRD_CAIF 822 +#define ARPHRD_IP6GRE 823 +#define ARPHRD_NETLINK 824 +#define ARPHRD_6LOWPAN 825 +#define ARPHRD_VSOCKMON 826 + +#define ARPHRD_VOID 0xFFFF +#define ARPHRD_NONE 0xFFFE + +struct arpreq { + struct sockaddr arp_pa; + struct sockaddr arp_ha; + int arp_flags; + struct sockaddr arp_netmask; + char arp_dev[16]; +}; + +struct arpreq_old { + struct sockaddr arp_pa; + struct sockaddr arp_ha; + int arp_flags; + struct sockaddr arp_netmask; +}; + +#define ATF_COM 0x02 +#define ATF_PERM 0x04 +#define ATF_PUBL 0x08 +#define ATF_USETRAILERS 0x10 +#define ATF_NETMASK 0x20 +#define ATF_DONTPUB 0x40 +#define ATF_MAGIC 0x80 + +#define ARPD_UPDATE 0x01 +#define ARPD_LOOKUP 0x02 +#define ARPD_FLUSH 0x03 + +struct arpd_request { + unsigned short req; + uint32_t ip; + unsigned long dev; + unsigned long stamp; + unsigned long updated; + unsigned char ha[MAX_ADDR_LEN]; +}; + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/net/route.h b/c/common/test/includes/standard-library/net/route.h new file mode 100644 index 0000000000..96ff48e014 --- /dev/null +++ b/c/common/test/includes/standard-library/net/route.h @@ -0,0 +1,124 @@ +#ifndef _NET_ROUTE_H +#define _NET_ROUTE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + + +struct rtentry { + unsigned long int rt_pad1; + struct sockaddr rt_dst; + struct sockaddr rt_gateway; + struct sockaddr rt_genmask; + unsigned short int rt_flags; + short int rt_pad2; + unsigned long int rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; + short int rt_pad4[sizeof(long)/2-1]; + short int rt_metric; + char *rt_dev; + unsigned long int rt_mtu; + unsigned long int rt_window; + unsigned short int rt_irtt; +}; + +#define rt_mss rt_mtu + + +struct in6_rtmsg { + struct in6_addr rtmsg_dst; + struct in6_addr rtmsg_src; + struct in6_addr rtmsg_gateway; + uint32_t rtmsg_type; + uint16_t rtmsg_dst_len; + uint16_t rtmsg_src_len; + uint32_t rtmsg_metric; + unsigned long int rtmsg_info; + uint32_t rtmsg_flags; + int rtmsg_ifindex; +}; + + +#define RTF_UP 0x0001 +#define RTF_GATEWAY 0x0002 + +#define RTF_HOST 0x0004 +#define RTF_REINSTATE 0x0008 +#define RTF_DYNAMIC 0x0010 +#define RTF_MODIFIED 0x0020 +#define RTF_MTU 0x0040 +#define RTF_MSS RTF_MTU +#define RTF_WINDOW 0x0080 +#define RTF_IRTT 0x0100 +#define RTF_REJECT 0x0200 +#define RTF_STATIC 0x0400 +#define RTF_XRESOLVE 0x0800 +#define RTF_NOFORWARD 0x1000 +#define RTF_THROW 0x2000 +#define RTF_NOPMTUDISC 0x4000 + +#define RTF_DEFAULT 0x00010000 +#define RTF_ALLONLINK 0x00020000 +#define RTF_ADDRCONF 0x00040000 + +#define RTF_LINKRT 0x00100000 +#define RTF_NONEXTHOP 0x00200000 + +#define RTF_CACHE 0x01000000 +#define RTF_FLOW 0x02000000 +#define RTF_POLICY 0x04000000 + +#define RTCF_VALVE 0x00200000 +#define RTCF_MASQ 0x00400000 +#define RTCF_NAT 0x00800000 +#define RTCF_DOREDIRECT 0x01000000 +#define RTCF_LOG 0x02000000 +#define RTCF_DIRECTSRC 0x04000000 + +#define RTF_LOCAL 0x80000000 +#define RTF_INTERFACE 0x40000000 +#define RTF_MULTICAST 0x20000000 +#define RTF_BROADCAST 0x10000000 +#define RTF_NAT 0x08000000 + +#define RTF_ADDRCLASSMASK 0xF8000000 +#define RT_ADDRCLASS(flags) ((uint32_t) flags >> 23) + +#define RT_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +#define RT_LOCALADDR(flags) ((flags & RTF_ADDRCLASSMASK) \ + == (RTF_LOCAL|RTF_INTERFACE)) + +#define RT_CLASS_UNSPEC 0 +#define RT_CLASS_DEFAULT 253 + +#define RT_CLASS_MAIN 254 +#define RT_CLASS_LOCAL 255 +#define RT_CLASS_MAX 255 + + +#define RTMSG_ACK NLMSG_ACK +#define RTMSG_OVERRUN NLMSG_OVERRUN + +#define RTMSG_NEWDEVICE 0x11 +#define RTMSG_DELDEVICE 0x12 +#define RTMSG_NEWROUTE 0x21 +#define RTMSG_DELROUTE 0x22 +#define RTMSG_NEWRULE 0x31 +#define RTMSG_DELRULE 0x32 +#define RTMSG_CONTROL 0x40 + +#define RTMSG_AR_FAILED 0x51 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netdb.h b/c/common/test/includes/standard-library/netdb.h new file mode 100644 index 0000000000..d096c78183 --- /dev/null +++ b/c/common/test/includes/standard-library/netdb.h @@ -0,0 +1,156 @@ +#ifndef _NETDB_H +#define _NETDB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_size_t +#include +#endif + +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; + +#define AI_PASSIVE 0x01 +#define AI_CANONNAME 0x02 +#define AI_NUMERICHOST 0x04 +#define AI_V4MAPPED 0x08 +#define AI_ALL 0x10 +#define AI_ADDRCONFIG 0x20 +#define AI_NUMERICSERV 0x400 + + +#define NI_NUMERICHOST 0x01 +#define NI_NUMERICSERV 0x02 +#define NI_NOFQDN 0x04 +#define NI_NAMEREQD 0x08 +#define NI_DGRAM 0x10 +#define NI_NUMERICSCOPE 0x100 + +#define EAI_BADFLAGS -1 +#define EAI_NONAME -2 +#define EAI_AGAIN -3 +#define EAI_FAIL -4 +#define EAI_FAMILY -6 +#define EAI_SOCKTYPE -7 +#define EAI_SERVICE -8 +#define EAI_MEMORY -10 +#define EAI_SYSTEM -11 +#define EAI_OVERFLOW -12 + +int getaddrinfo (const char *__restrict, const char *__restrict, const struct addrinfo *__restrict, struct addrinfo **__restrict); +void freeaddrinfo (struct addrinfo *); +int getnameinfo (const struct sockaddr *__restrict, socklen_t, char *__restrict, socklen_t, char *__restrict, socklen_t, int); +const char *gai_strerror(int); + + +/* Legacy functions follow (marked OBsolete in SUS) */ + +struct netent { + char *n_name; + char **n_aliases; + int n_addrtype; + uint32_t n_net; +}; + +struct hostent { + char *h_name; + char **h_aliases; + int h_addrtype; + int h_length; + char **h_addr_list; +}; +#define h_addr h_addr_list[0] + +struct servent { + char *s_name; + char **s_aliases; + int s_port; + char *s_proto; +}; + +struct protoent { + char *p_name; + char **p_aliases; + int p_proto; +}; + +void sethostent (int); +void endhostent (void); +struct hostent *gethostent (void); + +void setnetent (int); +void endnetent (void); +struct netent *getnetent (void); +struct netent *getnetbyaddr (uint32_t, int); +struct netent *getnetbyname (const char *); + +void setservent (int); +void endservent (void); +struct servent *getservent (void); +struct servent *getservbyname (const char *, const char *); +struct servent *getservbyport (int, const char *); + +void setprotoent (int); +void endprotoent (void); +struct protoent *getprotoent (void); +struct protoent *getprotobyname (const char *); +struct protoent *getprotobynumber (int); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ + || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) +struct hostent *gethostbyname (const char *); +struct hostent *gethostbyaddr (const void *, socklen_t, int); +#ifdef __GNUC__ +__attribute__((const)) +#endif +int *__h_errno_location(void); +#define h_errno (*__h_errno_location()) +#define HOST_NOT_FOUND 1 +#define TRY_AGAIN 2 +#define NO_RECOVERY 3 +#define NO_DATA 4 +#define NO_ADDRESS NO_DATA +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +void herror(const char *); +const char *hstrerror(int); +int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *); +int gethostbyname2_r(const char *, int, struct hostent *, char *, size_t, struct hostent **, int *); +struct hostent *gethostbyname2(const char *, int); +int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, char *, size_t, struct hostent **, int *); +int getservbyport_r(int, const char *, struct servent *, char *, size_t, struct servent **); +int getservbyname_r(const char *, const char *, struct servent *, char *, size_t, struct servent **); +#define EAI_NODATA -5 +#define EAI_ADDRFAMILY -9 +#define EAI_INPROGRESS -100 +#define EAI_CANCELED -101 +#define EAI_NOTCANCELED -102 +#define EAI_ALLDONE -103 +#define EAI_INTR -104 +#define EAI_IDN_ENCODE -105 +#define NI_MAXHOST 255 +#define NI_MAXSERV 32 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/ether.h b/c/common/test/includes/standard-library/netinet/ether.h new file mode 100644 index 0000000000..eec7e53ca4 --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/ether.h @@ -0,0 +1,22 @@ +#ifndef _NETINET_ETHER_H +#define _NETINET_ETHER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +char *ether_ntoa (const struct ether_addr *); +struct ether_addr *ether_aton (const char *); +char *ether_ntoa_r (const struct ether_addr *, char *); +struct ether_addr *ether_aton_r (const char *, struct ether_addr *); +int ether_line(const char *, struct ether_addr *, char *); +int ether_ntohost(char *, const struct ether_addr *); +int ether_hostton(const char *, struct ether_addr *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/icmp6.h b/c/common/test/includes/standard-library/netinet/icmp6.h new file mode 100644 index 0000000000..01269e7d4a --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/icmp6.h @@ -0,0 +1,305 @@ +#ifndef _NETINET_ICMP6_H +#define _NETINET_ICMP6_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#define ICMP6_FILTER 1 + +#define ICMP6_FILTER_BLOCK 1 +#define ICMP6_FILTER_PASS 2 +#define ICMP6_FILTER_BLOCKOTHERS 3 +#define ICMP6_FILTER_PASSONLY 4 + +struct icmp6_filter { + uint32_t icmp6_filt[8]; +}; + +struct icmp6_hdr { + uint8_t icmp6_type; + uint8_t icmp6_code; + uint16_t icmp6_cksum; + union { + uint32_t icmp6_un_data32[1]; + uint16_t icmp6_un_data16[2]; + uint8_t icmp6_un_data8[4]; + } icmp6_dataun; +}; + +#define icmp6_data32 icmp6_dataun.icmp6_un_data32 +#define icmp6_data16 icmp6_dataun.icmp6_un_data16 +#define icmp6_data8 icmp6_dataun.icmp6_un_data8 +#define icmp6_pptr icmp6_data32[0] +#define icmp6_mtu icmp6_data32[0] +#define icmp6_id icmp6_data16[0] +#define icmp6_seq icmp6_data16[1] +#define icmp6_maxdelay icmp6_data16[0] + +#define ICMP6_DST_UNREACH 1 +#define ICMP6_PACKET_TOO_BIG 2 +#define ICMP6_TIME_EXCEEDED 3 +#define ICMP6_PARAM_PROB 4 + +#define ICMP6_INFOMSG_MASK 0x80 + +#define ICMP6_ECHO_REQUEST 128 +#define ICMP6_ECHO_REPLY 129 +#define MLD_LISTENER_QUERY 130 +#define MLD_LISTENER_REPORT 131 +#define MLD_LISTENER_REDUCTION 132 + +#define ICMP6_DST_UNREACH_NOROUTE 0 +#define ICMP6_DST_UNREACH_ADMIN 1 +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 +#define ICMP6_DST_UNREACH_ADDR 3 +#define ICMP6_DST_UNREACH_NOPORT 4 + +#define ICMP6_TIME_EXCEED_TRANSIT 0 +#define ICMP6_TIME_EXCEED_REASSEMBLY 1 + +#define ICMP6_PARAMPROB_HEADER 0 +#define ICMP6_PARAMPROB_NEXTHEADER 1 +#define ICMP6_PARAMPROB_OPTION 2 + +#define ICMP6_FILTER_WILLPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0) + +#define ICMP6_FILTER_WILLBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0) + +#define ICMP6_FILTER_SETPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))) + +#define ICMP6_FILTER_SETBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))) + +#define ICMP6_FILTER_SETPASSALL(filterp) \ + memset (filterp, 0, sizeof (struct icmp6_filter)); + +#define ICMP6_FILTER_SETBLOCKALL(filterp) \ + memset (filterp, 0xFF, sizeof (struct icmp6_filter)); + +#define ND_ROUTER_SOLICIT 133 +#define ND_ROUTER_ADVERT 134 +#define ND_NEIGHBOR_SOLICIT 135 +#define ND_NEIGHBOR_ADVERT 136 +#define ND_REDIRECT 137 + +struct nd_router_solicit { + struct icmp6_hdr nd_rs_hdr; +}; + +#define nd_rs_type nd_rs_hdr.icmp6_type +#define nd_rs_code nd_rs_hdr.icmp6_code +#define nd_rs_cksum nd_rs_hdr.icmp6_cksum +#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] + +struct nd_router_advert { + struct icmp6_hdr nd_ra_hdr; + uint32_t nd_ra_reachable; + uint32_t nd_ra_retransmit; +}; + +#define nd_ra_type nd_ra_hdr.icmp6_type +#define nd_ra_code nd_ra_hdr.icmp6_code +#define nd_ra_cksum nd_ra_hdr.icmp6_cksum +#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] +#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] +#define ND_RA_FLAG_MANAGED 0x80 +#define ND_RA_FLAG_OTHER 0x40 +#define ND_RA_FLAG_HOME_AGENT 0x20 +#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] + +struct nd_neighbor_solicit { + struct icmp6_hdr nd_ns_hdr; + struct in6_addr nd_ns_target; +}; + +#define nd_ns_type nd_ns_hdr.icmp6_type +#define nd_ns_code nd_ns_hdr.icmp6_code +#define nd_ns_cksum nd_ns_hdr.icmp6_cksum +#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] + +struct nd_neighbor_advert { + struct icmp6_hdr nd_na_hdr; + struct in6_addr nd_na_target; +}; + +#define nd_na_type nd_na_hdr.icmp6_type +#define nd_na_code nd_na_hdr.icmp6_code +#define nd_na_cksum nd_na_hdr.icmp6_cksum +#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] +#if __BYTE_ORDER == __BIG_ENDIAN +#define ND_NA_FLAG_ROUTER 0x80000000 +#define ND_NA_FLAG_SOLICITED 0x40000000 +#define ND_NA_FLAG_OVERRIDE 0x20000000 +#else +#define ND_NA_FLAG_ROUTER 0x00000080 +#define ND_NA_FLAG_SOLICITED 0x00000040 +#define ND_NA_FLAG_OVERRIDE 0x00000020 +#endif + +struct nd_redirect { + struct icmp6_hdr nd_rd_hdr; + struct in6_addr nd_rd_target; + struct in6_addr nd_rd_dst; +}; + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +struct nd_opt_hdr { + uint8_t nd_opt_type; + uint8_t nd_opt_len; +}; + +#define ND_OPT_SOURCE_LINKADDR 1 +#define ND_OPT_TARGET_LINKADDR 2 +#define ND_OPT_PREFIX_INFORMATION 3 +#define ND_OPT_REDIRECTED_HEADER 4 +#define ND_OPT_MTU 5 +#define ND_OPT_RTR_ADV_INTERVAL 7 +#define ND_OPT_HOME_AGENT_INFO 8 + +struct nd_opt_prefix_info { + uint8_t nd_opt_pi_type; + uint8_t nd_opt_pi_len; + uint8_t nd_opt_pi_prefix_len; + uint8_t nd_opt_pi_flags_reserved; + uint32_t nd_opt_pi_valid_time; + uint32_t nd_opt_pi_preferred_time; + uint32_t nd_opt_pi_reserved2; + struct in6_addr nd_opt_pi_prefix; +}; + +#define ND_OPT_PI_FLAG_ONLINK 0x80 +#define ND_OPT_PI_FLAG_AUTO 0x40 +#define ND_OPT_PI_FLAG_RADDR 0x20 + +struct nd_opt_rd_hdr { + uint8_t nd_opt_rh_type; + uint8_t nd_opt_rh_len; + uint16_t nd_opt_rh_reserved1; + uint32_t nd_opt_rh_reserved2; +}; + +struct nd_opt_mtu { + uint8_t nd_opt_mtu_type; + uint8_t nd_opt_mtu_len; + uint16_t nd_opt_mtu_reserved; + uint32_t nd_opt_mtu_mtu; +}; + +struct mld_hdr { + struct icmp6_hdr mld_icmp6_hdr; + struct in6_addr mld_addr; +}; + +#define mld_type mld_icmp6_hdr.icmp6_type +#define mld_code mld_icmp6_hdr.icmp6_code +#define mld_cksum mld_icmp6_hdr.icmp6_cksum +#define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0] +#define mld_reserved mld_icmp6_hdr.icmp6_data16[1] + +#define ICMP6_ROUTER_RENUMBERING 138 + +struct icmp6_router_renum { + struct icmp6_hdr rr_hdr; + uint8_t rr_segnum; + uint8_t rr_flags; + uint16_t rr_maxdelay; + uint32_t rr_reserved; +}; + +#define rr_type rr_hdr.icmp6_type +#define rr_code rr_hdr.icmp6_code +#define rr_cksum rr_hdr.icmp6_cksum +#define rr_seqnum rr_hdr.icmp6_data32[0] + +#define ICMP6_RR_FLAGS_TEST 0x80 +#define ICMP6_RR_FLAGS_REQRESULT 0x40 +#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 +#define ICMP6_RR_FLAGS_SPECSITE 0x10 +#define ICMP6_RR_FLAGS_PREVDONE 0x08 + +struct rr_pco_match { + uint8_t rpm_code; + uint8_t rpm_len; + uint8_t rpm_ordinal; + uint8_t rpm_matchlen; + uint8_t rpm_minlen; + uint8_t rpm_maxlen; + uint16_t rpm_reserved; + struct in6_addr rpm_prefix; +}; + +#define RPM_PCO_ADD 1 +#define RPM_PCO_CHANGE 2 +#define RPM_PCO_SETGLOBAL 3 + +struct rr_pco_use { + uint8_t rpu_uselen; + uint8_t rpu_keeplen; + uint8_t rpu_ramask; + uint8_t rpu_raflags; + uint32_t rpu_vltime; + uint32_t rpu_pltime; + uint32_t rpu_flags; + struct in6_addr rpu_prefix; +}; + +#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x20 +#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10 + +#if __BYTE_ORDER == __BIG_ENDIAN +#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000 +#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000 +#else +#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80 +#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40 +#endif + +struct rr_result { + uint16_t rrr_flags; + uint8_t rrr_ordinal; + uint8_t rrr_matchedlen; + uint32_t rrr_ifid; + struct in6_addr rrr_prefix; +}; + +#if __BYTE_ORDER == __BIG_ENDIAN +#define ICMP6_RR_RESULT_FLAGS_OOB 0x0002 +#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001 +#else +#define ICMP6_RR_RESULT_FLAGS_OOB 0x0200 +#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100 +#endif + +struct nd_opt_adv_interval { + uint8_t nd_opt_adv_interval_type; + uint8_t nd_opt_adv_interval_len; + uint16_t nd_opt_adv_interval_reserved; + uint32_t nd_opt_adv_interval_ival; +}; + +struct nd_opt_home_agent_info { + uint8_t nd_opt_home_agent_info_type; + uint8_t nd_opt_home_agent_info_len; + uint16_t nd_opt_home_agent_info_reserved; + uint16_t nd_opt_home_agent_info_preference; + uint16_t nd_opt_home_agent_info_lifetime; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/if_ether.h b/c/common/test/includes/standard-library/netinet/if_ether.h new file mode 100644 index 0000000000..55a2ff1b17 --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/if_ether.h @@ -0,0 +1,148 @@ +#ifndef _NETINET_IF_ETHER_H +#define _NETINET_IF_ETHER_H + +#include +#include + +#define ETH_ALEN 6 +#define ETH_TLEN 2 +#define ETH_HLEN 14 +#define ETH_ZLEN 60 +#define ETH_DATA_LEN 1500 +#define ETH_FRAME_LEN 1514 +#define ETH_FCS_LEN 4 +#define ETH_MIN_MTU 68 +#define ETH_MAX_MTU 0xFFFFU + +#define ETH_P_LOOP 0x0060 +#define ETH_P_PUP 0x0200 +#define ETH_P_PUPAT 0x0201 +#define ETH_P_TSN 0x22F0 +#define ETH_P_ERSPAN2 0x22EB +#define ETH_P_IP 0x0800 +#define ETH_P_X25 0x0805 +#define ETH_P_ARP 0x0806 +#define ETH_P_BPQ 0x08FF +#define ETH_P_IEEEPUP 0x0a00 +#define ETH_P_IEEEPUPAT 0x0a01 +#define ETH_P_BATMAN 0x4305 +#define ETH_P_DEC 0x6000 +#define ETH_P_DNA_DL 0x6001 +#define ETH_P_DNA_RC 0x6002 +#define ETH_P_DNA_RT 0x6003 +#define ETH_P_LAT 0x6004 +#define ETH_P_DIAG 0x6005 +#define ETH_P_CUST 0x6006 +#define ETH_P_SCA 0x6007 +#define ETH_P_TEB 0x6558 +#define ETH_P_RARP 0x8035 +#define ETH_P_ATALK 0x809B +#define ETH_P_AARP 0x80F3 +#define ETH_P_8021Q 0x8100 +#define ETH_P_IPX 0x8137 +#define ETH_P_IPV6 0x86DD +#define ETH_P_PAUSE 0x8808 +#define ETH_P_SLOW 0x8809 +#define ETH_P_WCCP 0x883E +#define ETH_P_MPLS_UC 0x8847 +#define ETH_P_MPLS_MC 0x8848 +#define ETH_P_ATMMPOA 0x884c +#define ETH_P_PPP_DISC 0x8863 +#define ETH_P_PPP_SES 0x8864 +#define ETH_P_LINK_CTL 0x886c +#define ETH_P_ATMFATE 0x8884 +#define ETH_P_PAE 0x888E +#define ETH_P_AOE 0x88A2 +#define ETH_P_8021AD 0x88A8 +#define ETH_P_802_EX1 0x88B5 +#define ETH_P_ERSPAN 0x88BE +#define ETH_P_PREAUTH 0x88C7 +#define ETH_P_TIPC 0x88CA +#define ETH_P_LLDP 0x88CC +#define ETH_P_MRP 0x88E3 +#define ETH_P_MACSEC 0x88E5 +#define ETH_P_8021AH 0x88E7 +#define ETH_P_MVRP 0x88F5 +#define ETH_P_1588 0x88F7 +#define ETH_P_NCSI 0x88F8 +#define ETH_P_PRP 0x88FB +#define ETH_P_FCOE 0x8906 +#define ETH_P_TDLS 0x890D +#define ETH_P_FIP 0x8914 +#define ETH_P_IBOE 0x8915 +#define ETH_P_80221 0x8917 +#define ETH_P_HSR 0x892F +#define ETH_P_NSH 0x894F +#define ETH_P_LOOPBACK 0x9000 +#define ETH_P_QINQ1 0x9100 +#define ETH_P_QINQ2 0x9200 +#define ETH_P_QINQ3 0x9300 +#define ETH_P_EDSA 0xDADA +#define ETH_P_DSA_8021Q 0xDADB +#define ETH_P_IFE 0xED3E +#define ETH_P_AF_IUCV 0xFBFB + +#define ETH_P_802_3_MIN 0x0600 + +#define ETH_P_802_3 0x0001 +#define ETH_P_AX25 0x0002 +#define ETH_P_ALL 0x0003 +#define ETH_P_802_2 0x0004 +#define ETH_P_SNAP 0x0005 +#define ETH_P_DDCMP 0x0006 +#define ETH_P_WAN_PPP 0x0007 +#define ETH_P_PPP_MP 0x0008 +#define ETH_P_LOCALTALK 0x0009 +#define ETH_P_CAN 0x000C +#define ETH_P_CANFD 0x000D +#define ETH_P_PPPTALK 0x0010 +#define ETH_P_TR_802_2 0x0011 +#define ETH_P_MOBITEX 0x0015 +#define ETH_P_CONTROL 0x0016 +#define ETH_P_IRDA 0x0017 +#define ETH_P_ECONET 0x0018 +#define ETH_P_HDLC 0x0019 +#define ETH_P_ARCNET 0x001A +#define ETH_P_DSA 0x001B +#define ETH_P_TRAILER 0x001C +#define ETH_P_PHONET 0x00F5 +#define ETH_P_IEEE802154 0x00F6 +#define ETH_P_CAIF 0x00F7 +#define ETH_P_XDSA 0x00F8 +#define ETH_P_MAP 0x00F9 + +struct ethhdr { + uint8_t h_dest[ETH_ALEN]; + uint8_t h_source[ETH_ALEN]; + uint16_t h_proto; +}; + +#include +#include + +struct ether_arp { + struct arphdr ea_hdr; + uint8_t arp_sha[ETH_ALEN]; + uint8_t arp_spa[4]; + uint8_t arp_tha[ETH_ALEN]; + uint8_t arp_tpa[4]; +}; +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op + +#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ +do { \ + (enaddr)[0] = 0x01; \ + (enaddr)[1] = 0x00; \ + (enaddr)[2] = 0x5e; \ + (enaddr)[3] = ((uint8_t *)ipaddr)[1] & 0x7f; \ + (enaddr)[4] = ((uint8_t *)ipaddr)[2]; \ + (enaddr)[5] = ((uint8_t *)ipaddr)[3]; \ +} while(0) + +#define __UAPI_DEF_ETHHDR 0 + +#endif diff --git a/c/common/test/includes/standard-library/netinet/igmp.h b/c/common/test/includes/standard-library/netinet/igmp.h new file mode 100644 index 0000000000..bbe8206a10 --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/igmp.h @@ -0,0 +1,45 @@ +#ifndef _NETINET_IGMP_H +#define _NETINET_IGMP_H + +#include +#include + +struct igmp { + uint8_t igmp_type; + uint8_t igmp_code; + uint16_t igmp_cksum; + struct in_addr igmp_group; +}; + +#define IGMP_MINLEN 8 + +#define IGMP_MEMBERSHIP_QUERY 0x11 +#define IGMP_V1_MEMBERSHIP_REPORT 0x12 +#define IGMP_V2_MEMBERSHIP_REPORT 0x16 +#define IGMP_V2_LEAVE_GROUP 0x17 + +#define IGMP_DVMRP 0x13 +#define IGMP_PIM 0x14 +#define IGMP_TRACE 0x15 + +#define IGMP_MTRACE_RESP 0x1e +#define IGMP_MTRACE 0x1f + +#define IGMP_MAX_HOST_REPORT_DELAY 10 +#define IGMP_TIMER_SCALE 10 + +#define IGMP_DELAYING_MEMBER 1 +#define IGMP_IDLE_MEMBER 2 +#define IGMP_LAZY_MEMBER 3 +#define IGMP_SLEEPING_MEMBER 4 +#define IGMP_AWAKENING_MEMBER 5 + +#define IGMP_v1_ROUTER 1 +#define IGMP_v2_ROUTER 2 + +#define IGMP_HOST_MEMBERSHIP_QUERY IGMP_MEMBERSHIP_QUERY +#define IGMP_HOST_MEMBERSHIP_REPORT IGMP_V1_MEMBERSHIP_REPORT +#define IGMP_HOST_NEW_MEMBERSHIP_REPORT IGMP_V2_MEMBERSHIP_REPORT +#define IGMP_HOST_LEAVE_MESSAGE IGMP_V2_LEAVE_GROUP + +#endif diff --git a/c/common/test/includes/standard-library/netinet/in.h b/c/common/test/includes/standard-library/netinet/in.h new file mode 100644 index 0000000000..f9594339f0 --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/in.h @@ -0,0 +1,416 @@ +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +typedef uint16_t in_port_t; +typedef uint32_t in_addr_t; +struct in_addr { in_addr_t s_addr; }; + +struct sockaddr_in { + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; + uint8_t sin_zero[8]; +}; + +struct in6_addr { + union { + uint8_t __s6_addr[16]; + uint16_t __s6_addr16[8]; + uint32_t __s6_addr32[4]; + } __in6_union; +}; +#define s6_addr __in6_union.__s6_addr +#define s6_addr16 __in6_union.__s6_addr16 +#define s6_addr32 __in6_union.__s6_addr32 + +struct sockaddr_in6 { + sa_family_t sin6_family; + in_port_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; +}; + +struct ipv6_mreq { + struct in6_addr ipv6mr_multiaddr; + unsigned ipv6mr_interface; +}; + +#define INADDR_ANY ((in_addr_t) 0x00000000) +#define INADDR_BROADCAST ((in_addr_t) 0xffffffff) +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) + +#define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) +#define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) +#define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) +#define INADDR_ALLSNOOPERS_GROUP ((in_addr_t) 0xe000006a) +#define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) + +#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } +#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } + +extern const struct in6_addr in6addr_any, in6addr_loopback; + +#define INET_ADDRSTRLEN 16 +#define INET6_ADDRSTRLEN 46 + +uint32_t htonl(uint32_t); +uint16_t htons(uint16_t); +uint32_t ntohl(uint32_t); +uint16_t ntohs(uint16_t); + +#define IPPORT_RESERVED 1024 + +#define IPPROTO_IP 0 +#define IPPROTO_HOPOPTS 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_IGMP 2 +#define IPPROTO_IPIP 4 +#define IPPROTO_TCP 6 +#define IPPROTO_EGP 8 +#define IPPROTO_PUP 12 +#define IPPROTO_UDP 17 +#define IPPROTO_IDP 22 +#define IPPROTO_TP 29 +#define IPPROTO_DCCP 33 +#define IPPROTO_IPV6 41 +#define IPPROTO_ROUTING 43 +#define IPPROTO_FRAGMENT 44 +#define IPPROTO_RSVP 46 +#define IPPROTO_GRE 47 +#define IPPROTO_ESP 50 +#define IPPROTO_AH 51 +#define IPPROTO_ICMPV6 58 +#define IPPROTO_NONE 59 +#define IPPROTO_DSTOPTS 60 +#define IPPROTO_MTP 92 +#define IPPROTO_BEETPH 94 +#define IPPROTO_ENCAP 98 +#define IPPROTO_PIM 103 +#define IPPROTO_COMP 108 +#define IPPROTO_SCTP 132 +#define IPPROTO_MH 135 +#define IPPROTO_UDPLITE 136 +#define IPPROTO_MPLS 137 +#define IPPROTO_ETHERNET 143 +#define IPPROTO_RAW 255 +#define IPPROTO_MPTCP 262 +#define IPPROTO_MAX 263 + +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \ + ((uint32_t *) (a))[2] == 0 && ((uint32_t *) (a))[3] == 0) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \ + ((uint32_t *) (a))[2] == 0 && \ + ((uint8_t *) (a))[12] == 0 && ((uint8_t *) (a))[13] == 0 && \ + ((uint8_t *) (a))[14] == 0 && ((uint8_t *) (a))[15] == 1 ) + +#define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((uint8_t *) (a))[0]) == 0xfe && (((uint8_t *) (a))[1] & 0xc0) == 0x80) + +#define IN6_IS_ADDR_SITELOCAL(a) \ + ((((uint8_t *) (a))[0]) == 0xfe && (((uint8_t *) (a))[1] & 0xc0) == 0xc0) + +#define IN6_IS_ADDR_V4MAPPED(a) \ + (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \ + ((uint8_t *) (a))[8] == 0 && ((uint8_t *) (a))[9] == 0 && \ + ((uint8_t *) (a))[10] == 0xff && ((uint8_t *) (a))[11] == 0xff) + +#define IN6_IS_ADDR_V4COMPAT(a) \ + (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \ + ((uint32_t *) (a))[2] == 0 && ((uint8_t *) (a))[15] > 1) + +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x1)) + +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x2)) + +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x5)) + +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x8)) + +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0xe)) + +#define __ARE_4_EQUAL(a,b) \ + (!( (0[a]-0[b]) | (1[a]-1[b]) | (2[a]-2[b]) | (3[a]-3[b]) )) +#define IN6_ARE_ADDR_EQUAL(a,b) \ + __ARE_4_EQUAL((const uint32_t *)(a), (const uint32_t *)(b)) + +#define IN_CLASSA(a) ((((in_addr_t)(a)) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 +#define IN_CLASSB(a) ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 +#define IN_CLASSC(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) +#define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(a) IN_CLASSD(a) +#define IN_EXPERIMENTAL(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000) +#define IN_BADCLASS(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000) + +#define IN_LOOPBACKNET 127 + + +#define IP_TOS 1 +#define IP_TTL 2 +#define IP_HDRINCL 3 +#define IP_OPTIONS 4 +#define IP_ROUTER_ALERT 5 +#define IP_RECVOPTS 6 +#define IP_RETOPTS 7 +#define IP_PKTINFO 8 +#define IP_PKTOPTIONS 9 +#define IP_PMTUDISC 10 +#define IP_MTU_DISCOVER 10 +#define IP_RECVERR 11 +#define IP_RECVTTL 12 +#define IP_RECVTOS 13 +#define IP_MTU 14 +#define IP_FREEBIND 15 +#define IP_IPSEC_POLICY 16 +#define IP_XFRM_POLICY 17 +#define IP_PASSSEC 18 +#define IP_TRANSPARENT 19 +#define IP_ORIGDSTADDR 20 +#define IP_RECVORIGDSTADDR IP_ORIGDSTADDR +#define IP_MINTTL 21 +#define IP_NODEFRAG 22 +#define IP_CHECKSUM 23 +#define IP_BIND_ADDRESS_NO_PORT 24 +#define IP_RECVFRAGSIZE 25 +#define IP_RECVERR_RFC4884 26 +#define IP_MULTICAST_IF 32 +#define IP_MULTICAST_TTL 33 +#define IP_MULTICAST_LOOP 34 +#define IP_ADD_MEMBERSHIP 35 +#define IP_DROP_MEMBERSHIP 36 +#define IP_UNBLOCK_SOURCE 37 +#define IP_BLOCK_SOURCE 38 +#define IP_ADD_SOURCE_MEMBERSHIP 39 +#define IP_DROP_SOURCE_MEMBERSHIP 40 +#define IP_MSFILTER 41 +#define IP_MULTICAST_ALL 49 +#define IP_UNICAST_IF 50 + +#define IP_RECVRETOPTS IP_RETOPTS + +#define IP_PMTUDISC_DONT 0 +#define IP_PMTUDISC_WANT 1 +#define IP_PMTUDISC_DO 2 +#define IP_PMTUDISC_PROBE 3 +#define IP_PMTUDISC_INTERFACE 4 +#define IP_PMTUDISC_OMIT 5 + +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 +#define IP_MAX_MEMBERSHIPS 20 + +struct ip_opts { + struct in_addr ip_dst; + char ip_opts[40]; +}; + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +#define MCAST_JOIN_GROUP 42 +#define MCAST_BLOCK_SOURCE 43 +#define MCAST_UNBLOCK_SOURCE 44 +#define MCAST_LEAVE_GROUP 45 +#define MCAST_JOIN_SOURCE_GROUP 46 +#define MCAST_LEAVE_SOURCE_GROUP 47 +#define MCAST_MSFILTER 48 + +#define MCAST_EXCLUDE 0 +#define MCAST_INCLUDE 1 + +struct ip_mreq { + struct in_addr imr_multiaddr; + struct in_addr imr_interface; +}; + +struct ip_mreqn { + struct in_addr imr_multiaddr; + struct in_addr imr_address; + int imr_ifindex; +}; + +struct ip_mreq_source { + struct in_addr imr_multiaddr; + struct in_addr imr_interface; + struct in_addr imr_sourceaddr; +}; + +struct ip_msfilter { + struct in_addr imsf_multiaddr; + struct in_addr imsf_interface; + uint32_t imsf_fmode; + uint32_t imsf_numsrc; + struct in_addr imsf_slist[1]; +}; +#define IP_MSFILTER_SIZE(numsrc) \ + (sizeof(struct ip_msfilter) - sizeof(struct in_addr) \ + + (numsrc) * sizeof(struct in_addr)) + +struct group_req { + uint32_t gr_interface; + struct sockaddr_storage gr_group; +}; + +struct group_source_req { + uint32_t gsr_interface; + struct sockaddr_storage gsr_group; + struct sockaddr_storage gsr_source; +}; + +struct group_filter { + uint32_t gf_interface; + struct sockaddr_storage gf_group; + uint32_t gf_fmode; + uint32_t gf_numsrc; + struct sockaddr_storage gf_slist[1]; +}; +#define GROUP_FILTER_SIZE(numsrc) \ + (sizeof(struct group_filter) - sizeof(struct sockaddr_storage) \ + + (numsrc) * sizeof(struct sockaddr_storage)) + +struct in_pktinfo { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; +}; + +struct in6_pktinfo { + struct in6_addr ipi6_addr; + unsigned ipi6_ifindex; +}; + +struct ip6_mtuinfo { + struct sockaddr_in6 ip6m_addr; + uint32_t ip6m_mtu; +}; +#endif + +#define IPV6_ADDRFORM 1 +#define IPV6_2292PKTINFO 2 +#define IPV6_2292HOPOPTS 3 +#define IPV6_2292DSTOPTS 4 +#define IPV6_2292RTHDR 5 +#define IPV6_2292PKTOPTIONS 6 +#define IPV6_CHECKSUM 7 +#define IPV6_2292HOPLIMIT 8 +#define IPV6_NEXTHOP 9 +#define IPV6_AUTHHDR 10 +#define IPV6_UNICAST_HOPS 16 +#define IPV6_MULTICAST_IF 17 +#define IPV6_MULTICAST_HOPS 18 +#define IPV6_MULTICAST_LOOP 19 +#define IPV6_JOIN_GROUP 20 +#define IPV6_LEAVE_GROUP 21 +#define IPV6_ROUTER_ALERT 22 +#define IPV6_MTU_DISCOVER 23 +#define IPV6_MTU 24 +#define IPV6_RECVERR 25 +#define IPV6_V6ONLY 26 +#define IPV6_JOIN_ANYCAST 27 +#define IPV6_LEAVE_ANYCAST 28 +#define IPV6_MULTICAST_ALL 29 +#define IPV6_ROUTER_ALERT_ISOLATE 30 +#define IPV6_IPSEC_POLICY 34 +#define IPV6_XFRM_POLICY 35 +#define IPV6_HDRINCL 36 + +#define IPV6_RECVPKTINFO 49 +#define IPV6_PKTINFO 50 +#define IPV6_RECVHOPLIMIT 51 +#define IPV6_HOPLIMIT 52 +#define IPV6_RECVHOPOPTS 53 +#define IPV6_HOPOPTS 54 +#define IPV6_RTHDRDSTOPTS 55 +#define IPV6_RECVRTHDR 56 +#define IPV6_RTHDR 57 +#define IPV6_RECVDSTOPTS 58 +#define IPV6_DSTOPTS 59 +#define IPV6_RECVPATHMTU 60 +#define IPV6_PATHMTU 61 +#define IPV6_DONTFRAG 62 +#define IPV6_RECVTCLASS 66 +#define IPV6_TCLASS 67 +#define IPV6_AUTOFLOWLABEL 70 +#define IPV6_ADDR_PREFERENCES 72 +#define IPV6_MINHOPCOUNT 73 +#define IPV6_ORIGDSTADDR 74 +#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR +#define IPV6_TRANSPARENT 75 +#define IPV6_UNICAST_IF 76 +#define IPV6_RECVFRAGSIZE 77 +#define IPV6_FREEBIND 78 + +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#define IPV6_RXHOPOPTS IPV6_HOPOPTS +#define IPV6_RXDSTOPTS IPV6_DSTOPTS + +#define IPV6_PMTUDISC_DONT 0 +#define IPV6_PMTUDISC_WANT 1 +#define IPV6_PMTUDISC_DO 2 +#define IPV6_PMTUDISC_PROBE 3 +#define IPV6_PMTUDISC_INTERFACE 4 +#define IPV6_PMTUDISC_OMIT 5 + +#define IPV6_PREFER_SRC_TMP 0x0001 +#define IPV6_PREFER_SRC_PUBLIC 0x0002 +#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100 +#define IPV6_PREFER_SRC_COA 0x0004 +#define IPV6_PREFER_SRC_HOME 0x0400 +#define IPV6_PREFER_SRC_CGA 0x0008 +#define IPV6_PREFER_SRC_NONCGA 0x0800 + +#define IPV6_RTHDR_LOOSE 0 +#define IPV6_RTHDR_STRICT 1 + +#define IPV6_RTHDR_TYPE_0 0 + +#define __UAPI_DEF_IN_ADDR 0 +#define __UAPI_DEF_IN_IPPROTO 0 +#define __UAPI_DEF_IN_PKTINFO 0 +#define __UAPI_DEF_IP_MREQ 0 +#define __UAPI_DEF_SOCKADDR_IN 0 +#define __UAPI_DEF_IN_CLASS 0 +#define __UAPI_DEF_IN6_ADDR 0 +#define __UAPI_DEF_IN6_ADDR_ALT 0 +#define __UAPI_DEF_SOCKADDR_IN6 0 +#define __UAPI_DEF_IPV6_MREQ 0 +#define __UAPI_DEF_IPPROTO_V6 0 +#define __UAPI_DEF_IPV6_OPTIONS 0 +#define __UAPI_DEF_IN6_PKTINFO 0 +#define __UAPI_DEF_IP6_MTUINFO 0 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/in_systm.h b/c/common/test/includes/standard-library/netinet/in_systm.h new file mode 100644 index 0000000000..a7b417722c --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/in_systm.h @@ -0,0 +1,9 @@ +#ifndef _NETINET_IN_SYSTM_H +#define _NETINET_IN_SYSTM_H + +#include + +typedef uint16_t n_short; +typedef uint32_t n_long, n_time; + +#endif diff --git a/c/common/test/includes/standard-library/netinet/ip.h b/c/common/test/includes/standard-library/netinet/ip.h new file mode 100644 index 0000000000..0ae132a585 --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/ip.h @@ -0,0 +1,199 @@ +#ifndef _NETINET_IP_H +#define _NETINET_IP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct timestamp { + uint8_t len; + uint8_t ptr; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int flags:4; + unsigned int overflow:4; +#else + unsigned int overflow:4; + unsigned int flags:4; +#endif + uint32_t data[9]; + }; + +struct iphdr { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ihl:4; + unsigned int version:4; +#else + unsigned int version:4; + unsigned int ihl:4; +#endif + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_t daddr; +}; + +struct ip { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl:4; + unsigned int ip_v:4; +#else + unsigned int ip_v:4; + unsigned int ip_hl:4; +#endif + uint8_t ip_tos; + uint16_t ip_len; + uint16_t ip_id; + uint16_t ip_off; + uint8_t ip_ttl; + uint8_t ip_p; + uint16_t ip_sum; + struct in_addr ip_src, ip_dst; +}; + +#define IP_RF 0x8000 +#define IP_DF 0x4000 +#define IP_MF 0x2000 +#define IP_OFFMASK 0x1fff + +struct ip_timestamp { + uint8_t ipt_code; + uint8_t ipt_len; + uint8_t ipt_ptr; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ipt_flg:4; + unsigned int ipt_oflw:4; +#else + unsigned int ipt_oflw:4; + unsigned int ipt_flg:4; +#endif + uint32_t data[9]; +}; + +#define IPVERSION 4 +#define IP_MAXPACKET 65535 + +#define IPTOS_ECN_MASK 0x03 +#define IPTOS_ECN(x) ((x) & IPTOS_ECN_MASK) +#define IPTOS_ECN_NOT_ECT 0x00 +#define IPTOS_ECN_ECT1 0x01 +#define IPTOS_ECN_ECT0 0x02 +#define IPTOS_ECN_CE 0x03 + +#define IPTOS_DSCP_MASK 0xfc +#define IPTOS_DSCP(x) ((x) & IPTOS_DSCP_MASK) +#define IPTOS_DSCP_AF11 0x28 +#define IPTOS_DSCP_AF12 0x30 +#define IPTOS_DSCP_AF13 0x38 +#define IPTOS_DSCP_AF21 0x48 +#define IPTOS_DSCP_AF22 0x50 +#define IPTOS_DSCP_AF23 0x58 +#define IPTOS_DSCP_AF31 0x68 +#define IPTOS_DSCP_AF32 0x70 +#define IPTOS_DSCP_AF33 0x78 +#define IPTOS_DSCP_AF41 0x88 +#define IPTOS_DSCP_AF42 0x90 +#define IPTOS_DSCP_AF43 0x98 +#define IPTOS_DSCP_EF 0xb8 + +#define IPTOS_CLASS_MASK 0xe0 +#define IPTOS_CLASS(x) ((x) & IPTOS_CLASS_MASK) +#define IPTOS_CLASS_CS0 0x00 +#define IPTOS_CLASS_CS1 0x20 +#define IPTOS_CLASS_CS2 0x40 +#define IPTOS_CLASS_CS3 0x60 +#define IPTOS_CLASS_CS4 0x80 +#define IPTOS_CLASS_CS5 0xa0 +#define IPTOS_CLASS_CS6 0xc0 +#define IPTOS_CLASS_CS7 0xe0 +#define IPTOS_CLASS_DEFAULT IPTOS_CLASS_CS0 + +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + +#define IPOPT_COPY 0x80 +#define IPOPT_CLASS_MASK 0x60 +#define IPOPT_NUMBER_MASK 0x1f + +#define IPOPT_COPIED(o) ((o) & IPOPT_COPY) +#define IPOPT_CLASS(o) ((o) & IPOPT_CLASS_MASK) +#define IPOPT_NUMBER(o) ((o) & IPOPT_NUMBER_MASK) + +#define IPOPT_CONTROL 0x00 +#define IPOPT_RESERVED1 0x20 +#define IPOPT_DEBMEAS 0x40 +#define IPOPT_MEASUREMENT IPOPT_DEBMEAS +#define IPOPT_RESERVED2 0x60 + +#define IPOPT_EOL 0 +#define IPOPT_END IPOPT_EOL +#define IPOPT_NOP 1 +#define IPOPT_NOOP IPOPT_NOP + +#define IPOPT_RR 7 +#define IPOPT_TS 68 +#define IPOPT_TIMESTAMP IPOPT_TS +#define IPOPT_SECURITY 130 +#define IPOPT_SEC IPOPT_SECURITY +#define IPOPT_LSRR 131 +#define IPOPT_SATID 136 +#define IPOPT_SID IPOPT_SATID +#define IPOPT_SSRR 137 +#define IPOPT_RA 148 + +#define IPOPT_OPTVAL 0 +#define IPOPT_OLEN 1 +#define IPOPT_OFFSET 2 +#define IPOPT_MINOFF 4 + +#define MAX_IPOPTLEN 40 + +#define IPOPT_TS_TSONLY 0 +#define IPOPT_TS_TSANDADDR 1 +#define IPOPT_TS_PRESPEC 3 + +#define IPOPT_SECUR_UNCLASS 0x0000 +#define IPOPT_SECUR_CONFID 0xf135 +#define IPOPT_SECUR_EFTO 0x789a +#define IPOPT_SECUR_MMMM 0xbc4d +#define IPOPT_SECUR_RESTR 0xaf13 +#define IPOPT_SECUR_SECRET 0xd788 +#define IPOPT_SECUR_TOPSECRET 0x6bc5 + +#define MAXTTL 255 +#define IPDEFTTL 64 +#define IPFRAGTTL 60 +#define IPTTLDEC 1 + +#define IP_MSS 576 + +#define __UAPI_DEF_IPHDR 0 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/ip6.h b/c/common/test/includes/standard-library/netinet/ip6.h new file mode 100644 index 0000000000..50c626a69c --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/ip6.h @@ -0,0 +1,141 @@ +#ifndef _NETINET_IP6_H +#define _NETINET_IP6_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct ip6_hdr { + union { + struct ip6_hdrctl { + uint32_t ip6_un1_flow; + uint16_t ip6_un1_plen; + uint8_t ip6_un1_nxt; + uint8_t ip6_un1_hlim; + } ip6_un1; + uint8_t ip6_un2_vfc; + } ip6_ctlun; + struct in6_addr ip6_src; + struct in6_addr ip6_dst; +}; + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +struct ip6_ext { + uint8_t ip6e_nxt; + uint8_t ip6e_len; +}; + +struct ip6_hbh { + uint8_t ip6h_nxt; + uint8_t ip6h_len; +}; + +struct ip6_dest { + uint8_t ip6d_nxt; + uint8_t ip6d_len; +}; + +struct ip6_rthdr { + uint8_t ip6r_nxt; + uint8_t ip6r_len; + uint8_t ip6r_type; + uint8_t ip6r_segleft; +}; + +struct ip6_rthdr0 { + uint8_t ip6r0_nxt; + uint8_t ip6r0_len; + uint8_t ip6r0_type; + uint8_t ip6r0_segleft; + uint8_t ip6r0_reserved; + uint8_t ip6r0_slmap[3]; + struct in6_addr ip6r0_addr[]; +}; + +struct ip6_frag { + uint8_t ip6f_nxt; + uint8_t ip6f_reserved; + uint16_t ip6f_offlg; + uint32_t ip6f_ident; +}; + +#if __BYTE_ORDER == __BIG_ENDIAN +#define IP6F_OFF_MASK 0xfff8 +#define IP6F_RESERVED_MASK 0x0006 +#define IP6F_MORE_FRAG 0x0001 +#else +#define IP6F_OFF_MASK 0xf8ff +#define IP6F_RESERVED_MASK 0x0600 +#define IP6F_MORE_FRAG 0x0100 +#endif + +struct ip6_opt { + uint8_t ip6o_type; + uint8_t ip6o_len; +}; + +#define IP6OPT_TYPE(o) ((o) & 0xc0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xc0 +#define IP6OPT_TYPE_MUTABLE 0x20 + +#define IP6OPT_PAD1 0 +#define IP6OPT_PADN 1 + +#define IP6OPT_JUMBO 0xc2 +#define IP6OPT_NSAP_ADDR 0xc3 +#define IP6OPT_TUNNEL_LIMIT 0x04 +#define IP6OPT_ROUTER_ALERT 0x05 + +struct ip6_opt_jumbo { + uint8_t ip6oj_type; + uint8_t ip6oj_len; + uint8_t ip6oj_jumbo_len[4]; +}; +#define IP6OPT_JUMBO_LEN 6 + +struct ip6_opt_nsap { + uint8_t ip6on_type; + uint8_t ip6on_len; + uint8_t ip6on_src_nsap_len; + uint8_t ip6on_dst_nsap_len; +}; + +struct ip6_opt_tunnel { + uint8_t ip6ot_type; + uint8_t ip6ot_len; + uint8_t ip6ot_encap_limit; +}; + +struct ip6_opt_router { + uint8_t ip6or_type; + uint8_t ip6or_len; + uint8_t ip6or_value[2]; +}; + +#if __BYTE_ORDER == __BIG_ENDIAN +#define IP6_ALERT_MLD 0x0000 +#define IP6_ALERT_RSVP 0x0001 +#define IP6_ALERT_AN 0x0002 +#else +#define IP6_ALERT_MLD 0x0000 +#define IP6_ALERT_RSVP 0x0100 +#define IP6_ALERT_AN 0x0200 +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/ip_icmp.h b/c/common/test/includes/standard-library/netinet/ip_icmp.h new file mode 100644 index 0000000000..b9e0df8997 --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/ip_icmp.h @@ -0,0 +1,193 @@ +#ifndef _NETINET_IP_ICMP_H +#define _NETINET_IP_ICMP_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct icmphdr { + uint8_t type; + uint8_t code; + uint16_t checksum; + union { + struct { + uint16_t id; + uint16_t sequence; + } echo; + uint32_t gateway; + struct { + uint16_t __unused; + uint16_t mtu; + } frag; + uint8_t reserved[4]; + } un; +}; + +#define ICMP_ECHOREPLY 0 +#define ICMP_DEST_UNREACH 3 +#define ICMP_SOURCE_QUENCH 4 +#define ICMP_REDIRECT 5 +#define ICMP_ECHO 8 +#define ICMP_TIME_EXCEEDED 11 +#define ICMP_PARAMETERPROB 12 +#define ICMP_TIMESTAMP 13 +#define ICMP_TIMESTAMPREPLY 14 +#define ICMP_INFO_REQUEST 15 +#define ICMP_INFO_REPLY 16 +#define ICMP_ADDRESS 17 +#define ICMP_ADDRESSREPLY 18 +#define NR_ICMP_TYPES 18 + + +#define ICMP_NET_UNREACH 0 +#define ICMP_HOST_UNREACH 1 +#define ICMP_PROT_UNREACH 2 +#define ICMP_PORT_UNREACH 3 +#define ICMP_FRAG_NEEDED 4 +#define ICMP_SR_FAILED 5 +#define ICMP_NET_UNKNOWN 6 +#define ICMP_HOST_UNKNOWN 7 +#define ICMP_HOST_ISOLATED 8 +#define ICMP_NET_ANO 9 +#define ICMP_HOST_ANO 10 +#define ICMP_NET_UNR_TOS 11 +#define ICMP_HOST_UNR_TOS 12 +#define ICMP_PKT_FILTERED 13 +#define ICMP_PREC_VIOLATION 14 +#define ICMP_PREC_CUTOFF 15 +#define NR_ICMP_UNREACH 15 + +#define ICMP_REDIR_NET 0 +#define ICMP_REDIR_HOST 1 +#define ICMP_REDIR_NETTOS 2 +#define ICMP_REDIR_HOSTTOS 3 + +#define ICMP_EXC_TTL 0 +#define ICMP_EXC_FRAGTIME 1 + + +struct icmp_ra_addr { + uint32_t ira_addr; + uint32_t ira_preference; +}; + +struct icmp { + uint8_t icmp_type; + uint8_t icmp_code; + uint16_t icmp_cksum; + union { + uint8_t ih_pptr; + struct in_addr ih_gwaddr; + struct ih_idseq { + uint16_t icd_id; + uint16_t icd_seq; + } ih_idseq; + uint32_t ih_void; + + struct ih_pmtu { + uint16_t ipm_void; + uint16_t ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv { + uint8_t irt_num_addrs; + uint8_t irt_wpa; + uint16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; + union { + struct { + uint32_t its_otime; + uint32_t its_rtime; + uint32_t its_ttime; + } id_ts; + struct { + struct ip idi_ip; + } id_ip; + struct icmp_ra_addr id_radv; + uint32_t id_mask; + uint8_t id_data[1]; + } icmp_dun; +}; + +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_radv icmp_dun.id_radv +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data + +#define ICMP_MINLEN 8 +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) +#define ICMP_MASKLEN 12 +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + +#define ICMP_UNREACH 3 +#define ICMP_SOURCEQUENCH 4 +#define ICMP_ROUTERADVERT 9 +#define ICMP_ROUTERSOLICIT 10 +#define ICMP_TIMXCEED 11 +#define ICMP_PARAMPROB 12 +#define ICMP_TSTAMP 13 +#define ICMP_TSTAMPREPLY 14 +#define ICMP_IREQ 15 +#define ICMP_IREQREPLY 16 +#define ICMP_MASKREQ 17 +#define ICMP_MASKREPLY 18 +#define ICMP_MAXTYPE 18 + +#define ICMP_UNREACH_NET 0 +#define ICMP_UNREACH_HOST 1 +#define ICMP_UNREACH_PROTOCOL 2 +#define ICMP_UNREACH_PORT 3 +#define ICMP_UNREACH_NEEDFRAG 4 +#define ICMP_UNREACH_SRCFAIL 5 +#define ICMP_UNREACH_NET_UNKNOWN 6 +#define ICMP_UNREACH_HOST_UNKNOWN 7 +#define ICMP_UNREACH_ISOLATED 8 +#define ICMP_UNREACH_NET_PROHIB 9 +#define ICMP_UNREACH_HOST_PROHIB 10 +#define ICMP_UNREACH_TOSNET 11 +#define ICMP_UNREACH_TOSHOST 12 +#define ICMP_UNREACH_FILTER_PROHIB 13 +#define ICMP_UNREACH_HOST_PRECEDENCE 14 +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 + +#define ICMP_REDIRECT_NET 0 +#define ICMP_REDIRECT_HOST 1 +#define ICMP_REDIRECT_TOSNET 2 +#define ICMP_REDIRECT_TOSHOST 3 + +#define ICMP_TIMXCEED_INTRANS 0 +#define ICMP_TIMXCEED_REASS 1 + +#define ICMP_PARAMPROB_OPTABSENT 1 + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/tcp.h b/c/common/test/includes/standard-library/netinet/tcp.h new file mode 100644 index 0000000000..b7b997f5fd --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/tcp.h @@ -0,0 +1,294 @@ +#ifndef _NETINET_TCP_H +#define _NETINET_TCP_H + +#include + +#define TCP_NODELAY 1 +#define TCP_MAXSEG 2 +#define TCP_CORK 3 +#define TCP_KEEPIDLE 4 +#define TCP_KEEPINTVL 5 +#define TCP_KEEPCNT 6 +#define TCP_SYNCNT 7 +#define TCP_LINGER2 8 +#define TCP_DEFER_ACCEPT 9 +#define TCP_WINDOW_CLAMP 10 +#define TCP_INFO 11 +#define TCP_QUICKACK 12 +#define TCP_CONGESTION 13 +#define TCP_MD5SIG 14 +#define TCP_THIN_LINEAR_TIMEOUTS 16 +#define TCP_THIN_DUPACK 17 +#define TCP_USER_TIMEOUT 18 +#define TCP_REPAIR 19 +#define TCP_REPAIR_QUEUE 20 +#define TCP_QUEUE_SEQ 21 +#define TCP_REPAIR_OPTIONS 22 +#define TCP_FASTOPEN 23 +#define TCP_TIMESTAMP 24 +#define TCP_NOTSENT_LOWAT 25 +#define TCP_CC_INFO 26 +#define TCP_SAVE_SYN 27 +#define TCP_SAVED_SYN 28 +#define TCP_REPAIR_WINDOW 29 +#define TCP_FASTOPEN_CONNECT 30 +#define TCP_ULP 31 +#define TCP_MD5SIG_EXT 32 +#define TCP_FASTOPEN_KEY 33 +#define TCP_FASTOPEN_NO_COOKIE 34 +#define TCP_ZEROCOPY_RECEIVE 35 +#define TCP_INQ 36 +#define TCP_TX_DELAY 37 + +#define TCP_CM_INQ TCP_INQ + +#define TCP_ESTABLISHED 1 +#define TCP_SYN_SENT 2 +#define TCP_SYN_RECV 3 +#define TCP_FIN_WAIT1 4 +#define TCP_FIN_WAIT2 5 +#define TCP_TIME_WAIT 6 +#define TCP_CLOSE 7 +#define TCP_CLOSE_WAIT 8 +#define TCP_LAST_ACK 9 +#define TCP_LISTEN 10 +#define TCP_CLOSING 11 + +enum { + TCP_NLA_PAD, + TCP_NLA_BUSY, + TCP_NLA_RWND_LIMITED, + TCP_NLA_SNDBUF_LIMITED, + TCP_NLA_DATA_SEGS_OUT, + TCP_NLA_TOTAL_RETRANS, + TCP_NLA_PACING_RATE, + TCP_NLA_DELIVERY_RATE, + TCP_NLA_SND_CWND, + TCP_NLA_REORDERING, + TCP_NLA_MIN_RTT, + TCP_NLA_RECUR_RETRANS, + TCP_NLA_DELIVERY_RATE_APP_LMT, + TCP_NLA_SNDQ_SIZE, + TCP_NLA_CA_STATE, + TCP_NLA_SND_SSTHRESH, + TCP_NLA_DELIVERED, + TCP_NLA_DELIVERED_CE, + TCP_NLA_BYTES_SENT, + TCP_NLA_BYTES_RETRANS, + TCP_NLA_DSACK_DUPS, + TCP_NLA_REORD_SEEN, + TCP_NLA_SRTT, + TCP_NLA_TIMEOUT_REHASH, + TCP_NLA_BYTES_NOTSENT, +}; + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define TCPOPT_EOL 0 +#define TCPOPT_NOP 1 +#define TCPOPT_MAXSEG 2 +#define TCPOPT_WINDOW 3 +#define TCPOPT_SACK_PERMITTED 4 +#define TCPOPT_SACK 5 +#define TCPOPT_TIMESTAMP 8 +#define TCPOLEN_SACK_PERMITTED 2 +#define TCPOLEN_WINDOW 3 +#define TCPOLEN_MAXSEG 4 +#define TCPOLEN_TIMESTAMP 10 + +#define SOL_TCP 6 + +#include +#include +#include + +typedef uint32_t tcp_seq; + +#define TH_FIN 0x01 +#define TH_SYN 0x02 +#define TH_RST 0x04 +#define TH_PUSH 0x08 +#define TH_ACK 0x10 +#define TH_URG 0x20 + +struct tcphdr { +#ifdef _GNU_SOURCE +#ifdef __GNUC__ + __extension__ +#endif + union { struct { + + uint16_t source; + uint16_t dest; + uint32_t seq; + uint32_t ack_seq; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint16_t res1:4; + uint16_t doff:4; + uint16_t fin:1; + uint16_t syn:1; + uint16_t rst:1; + uint16_t psh:1; + uint16_t ack:1; + uint16_t urg:1; + uint16_t res2:2; +#else + uint16_t doff:4; + uint16_t res1:4; + uint16_t res2:2; + uint16_t urg:1; + uint16_t ack:1; + uint16_t psh:1; + uint16_t rst:1; + uint16_t syn:1; + uint16_t fin:1; +#endif + uint16_t window; + uint16_t check; + uint16_t urg_ptr; + + }; struct { +#endif + + uint16_t th_sport; + uint16_t th_dport; + uint32_t th_seq; + uint32_t th_ack; +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t th_x2:4; + uint8_t th_off:4; +#else + uint8_t th_off:4; + uint8_t th_x2:4; +#endif + uint8_t th_flags; + uint16_t th_win; + uint16_t th_sum; + uint16_t th_urp; + +#ifdef _GNU_SOURCE + }; }; +#endif +}; +#endif + +#ifdef _GNU_SOURCE +#define TCPI_OPT_TIMESTAMPS 1 +#define TCPI_OPT_SACK 2 +#define TCPI_OPT_WSCALE 4 +#define TCPI_OPT_ECN 8 + +#define TCP_CA_Open 0 +#define TCP_CA_Disorder 1 +#define TCP_CA_CWR 2 +#define TCP_CA_Recovery 3 +#define TCP_CA_Loss 4 + +enum tcp_fastopen_client_fail { + TFO_STATUS_UNSPEC, + TFO_COOKIE_UNAVAILABLE, + TFO_DATA_NOT_ACKED, + TFO_SYN_RETRANSMITTED, +}; + +struct tcp_info { + uint8_t tcpi_state; + uint8_t tcpi_ca_state; + uint8_t tcpi_retransmits; + uint8_t tcpi_probes; + uint8_t tcpi_backoff; + uint8_t tcpi_options; + uint8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + uint8_t tcpi_delivery_rate_app_limited : 1, tcpi_fastopen_client_fail : 2; + uint32_t tcpi_rto; + uint32_t tcpi_ato; + uint32_t tcpi_snd_mss; + uint32_t tcpi_rcv_mss; + uint32_t tcpi_unacked; + uint32_t tcpi_sacked; + uint32_t tcpi_lost; + uint32_t tcpi_retrans; + uint32_t tcpi_fackets; + uint32_t tcpi_last_data_sent; + uint32_t tcpi_last_ack_sent; + uint32_t tcpi_last_data_recv; + uint32_t tcpi_last_ack_recv; + uint32_t tcpi_pmtu; + uint32_t tcpi_rcv_ssthresh; + uint32_t tcpi_rtt; + uint32_t tcpi_rttvar; + uint32_t tcpi_snd_ssthresh; + uint32_t tcpi_snd_cwnd; + uint32_t tcpi_advmss; + uint32_t tcpi_reordering; + uint32_t tcpi_rcv_rtt; + uint32_t tcpi_rcv_space; + uint32_t tcpi_total_retrans; + uint64_t tcpi_pacing_rate; + uint64_t tcpi_max_pacing_rate; + uint64_t tcpi_bytes_acked; + uint64_t tcpi_bytes_received; + uint32_t tcpi_segs_out; + uint32_t tcpi_segs_in; + uint32_t tcpi_notsent_bytes; + uint32_t tcpi_min_rtt; + uint32_t tcpi_data_segs_in; + uint32_t tcpi_data_segs_out; + uint64_t tcpi_delivery_rate; + uint64_t tcpi_busy_time; + uint64_t tcpi_rwnd_limited; + uint64_t tcpi_sndbuf_limited; + uint32_t tcpi_delivered; + uint32_t tcpi_delivered_ce; + uint64_t tcpi_bytes_sent; + uint64_t tcpi_bytes_retrans; + uint32_t tcpi_dsack_dups; + uint32_t tcpi_reord_seen; + uint32_t tcpi_rcv_ooopack; + uint32_t tcpi_snd_wnd; +}; + +#define TCP_MD5SIG_MAXKEYLEN 80 + +#define TCP_MD5SIG_FLAG_PREFIX 0x1 +#define TCP_MD5SIG_FLAG_IFINDEX 0x2 + +struct tcp_md5sig { + struct sockaddr_storage tcpm_addr; + uint8_t tcpm_flags; + uint8_t tcpm_prefixlen; + uint16_t tcpm_keylen; + int tcpm_ifindex; + uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; +}; + +struct tcp_diag_md5sig { + uint8_t tcpm_family; + uint8_t tcpm_prefixlen; + uint16_t tcpm_keylen; + uint32_t tcpm_addr[4]; + uint8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; +}; + +#define TCP_REPAIR_ON 1 +#define TCP_REPAIR_OFF 0 +#define TCP_REPAIR_OFF_NO_WP -1 + +struct tcp_repair_window { + uint32_t snd_wl1; + uint32_t snd_wnd; + uint32_t max_window; + uint32_t rcv_wnd; + uint32_t rcv_wup; +}; + +struct tcp_zerocopy_receive { + uint64_t address; + uint32_t length; + uint32_t recv_skip_hint; + uint32_t inq; + int32_t err; +}; + +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netinet/udp.h b/c/common/test/includes/standard-library/netinet/udp.h new file mode 100644 index 0000000000..40c3f2034d --- /dev/null +++ b/c/common/test/includes/standard-library/netinet/udp.h @@ -0,0 +1,46 @@ +#ifndef _NETINET_UDP_H +#define _NETINET_UDP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifdef _GNU_SOURCE +#define uh_sport source +#define uh_dport dest +#define uh_ulen len +#define uh_sum check +#endif + +struct udphdr { + uint16_t uh_sport; + uint16_t uh_dport; + uint16_t uh_ulen; + uint16_t uh_sum; +}; + +#define UDP_CORK 1 +#define UDP_ENCAP 100 +#define UDP_NO_CHECK6_TX 101 +#define UDP_NO_CHECK6_RX 102 +#define UDP_SEGMENT 103 +#define UDP_GRO 104 + +#define UDP_ENCAP_ESPINUDP_NON_IKE 1 +#define UDP_ENCAP_ESPINUDP 2 +#define UDP_ENCAP_L2TPINUDP 3 +#define UDP_ENCAP_GTP0 4 +#define UDP_ENCAP_GTP1U 5 +#define UDP_ENCAP_RXRPC 6 +#define TCP_ENCAP_ESPINTCP 7 + +#define SOL_UDP 17 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/netpacket/packet.h b/c/common/test/includes/standard-library/netpacket/packet.h new file mode 100644 index 0000000000..b36e092ad4 --- /dev/null +++ b/c/common/test/includes/standard-library/netpacket/packet.h @@ -0,0 +1,62 @@ +#ifndef _NETPACKET_PACKET_H +#define _NETPACKET_PACKET_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct sockaddr_ll { + unsigned short sll_family, sll_protocol; + int sll_ifindex; + unsigned short sll_hatype; + unsigned char sll_pkttype, sll_halen; + unsigned char sll_addr[8]; +}; + +struct packet_mreq { + int mr_ifindex; + unsigned short int mr_type, mr_alen; + unsigned char mr_address[8]; +}; + +#define PACKET_HOST 0 +#define PACKET_BROADCAST 1 +#define PACKET_MULTICAST 2 +#define PACKET_OTHERHOST 3 +#define PACKET_OUTGOING 4 +#define PACKET_LOOPBACK 5 +#define PACKET_FASTROUTE 6 + +#define PACKET_ADD_MEMBERSHIP 1 +#define PACKET_DROP_MEMBERSHIP 2 +#define PACKET_RECV_OUTPUT 3 +#define PACKET_RX_RING 5 +#define PACKET_STATISTICS 6 +#define PACKET_COPY_THRESH 7 +#define PACKET_AUXDATA 8 +#define PACKET_ORIGDEV 9 +#define PACKET_VERSION 10 +#define PACKET_HDRLEN 11 +#define PACKET_RESERVE 12 +#define PACKET_TX_RING 13 +#define PACKET_LOSS 14 +#define PACKET_VNET_HDR 15 +#define PACKET_TX_TIMESTAMP 16 +#define PACKET_TIMESTAMP 17 +#define PACKET_FANOUT 18 +#define PACKET_TX_HAS_OFF 19 +#define PACKET_QDISC_BYPASS 20 +#define PACKET_ROLLOVER_STATS 21 +#define PACKET_FANOUT_DATA 22 +#define PACKET_IGNORE_OUTGOING 23 + +#define PACKET_MR_MULTICAST 0 +#define PACKET_MR_PROMISC 1 +#define PACKET_MR_ALLMULTI 2 +#define PACKET_MR_UNICAST 3 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/nl_types.h b/c/common/test/includes/standard-library/nl_types.h new file mode 100644 index 0000000000..7c2d48e0f1 --- /dev/null +++ b/c/common/test/includes/standard-library/nl_types.h @@ -0,0 +1,22 @@ +#ifndef _NL_TYPES_H +#define _NL_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define NL_SETD 1 +#define NL_CAT_LOCALE 1 + +typedef int nl_item; +typedef void *nl_catd; + +nl_catd catopen (const char *, int); +char *catgets (nl_catd, int, int, const char *); +int catclose (nl_catd); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/paths.h b/c/common/test/includes/standard-library/paths.h new file mode 100644 index 0000000000..67de6b3c32 --- /dev/null +++ b/c/common/test/includes/standard-library/paths.h @@ -0,0 +1,31 @@ +#ifndef _PATHS_H +#define _PATHS_H + +#define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin" +#define _PATH_STDPATH "/bin:/usr/bin:/sbin:/usr/sbin" + +#define _PATH_BSHELL "/bin/sh" +#define _PATH_CONSOLE "/dev/console" +#define _PATH_DEVNULL "/dev/null" +#define _PATH_KLOG "/proc/kmsg" +#define _PATH_LASTLOG "/var/log/lastlog" +#define _PATH_MAILDIR "/var/mail" +#define _PATH_MAN "/usr/share/man" +#define _PATH_MNTTAB "/etc/fstab" +#define _PATH_MOUNTED "/etc/mtab" +#define _PATH_NOLOGIN "/etc/nologin" +#define _PATH_SENDMAIL "/usr/sbin/sendmail" +#define _PATH_SHADOW "/etc/shadow" +#define _PATH_SHELLS "/etc/shells" +#define _PATH_TTY "/dev/tty" +#define _PATH_UTMP "/dev/null/utmp" +#define _PATH_VI "/usr/bin/vi" +#define _PATH_WTMP "/dev/null/wtmp" + +#define _PATH_DEV "/dev/" +#define _PATH_TMP "/tmp/" +#define _PATH_VARDB "/var/lib/misc/" +#define _PATH_VARRUN "/var/run/" +#define _PATH_VARTMP "/var/tmp/" + +#endif diff --git a/c/common/test/includes/standard-library/poll.h b/c/common/test/includes/standard-library/poll.h new file mode 100644 index 0000000000..472e4b8470 --- /dev/null +++ b/c/common/test/includes/standard-library/poll.h @@ -0,0 +1,57 @@ +#ifndef _POLL_H +#define _POLL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#define POLLIN 0x001 +#define POLLPRI 0x002 +#define POLLOUT 0x004 +#define POLLERR 0x008 +#define POLLHUP 0x010 +#define POLLNVAL 0x020 +#define POLLRDNORM 0x040 +#define POLLRDBAND 0x080 +#ifndef POLLWRNORM +#define POLLWRNORM 0x100 +#define POLLWRBAND 0x200 +#endif +#ifndef POLLMSG +#define POLLMSG 0x400 +#define POLLRDHUP 0x2000 +#endif + +typedef unsigned long nfds_t; + +struct pollfd { + int fd; + short events; + short revents; +}; + +int poll (struct pollfd *, nfds_t, int); + +#ifdef _GNU_SOURCE +#define __NEED_time_t +#define __NEED_struct_timespec +#define __NEED_sigset_t +#include +int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *); +#endif + +#if _REDIR_TIME64 +#ifdef _GNU_SOURCE +__REDIR(ppoll, __ppoll_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/pthread.h b/c/common/test/includes/standard-library/pthread.h new file mode 100644 index 0000000000..0492f26a6b --- /dev/null +++ b/c/common/test/includes/standard-library/pthread.h @@ -0,0 +1,243 @@ +#ifndef _PTHREAD_H +#define _PTHREAD_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_time_t +#define __NEED_clockid_t +#define __NEED_struct_timespec +#define __NEED_sigset_t +#define __NEED_pthread_t +#define __NEED_pthread_attr_t +#define __NEED_pthread_mutexattr_t +#define __NEED_pthread_condattr_t +#define __NEED_pthread_rwlockattr_t +#define __NEED_pthread_barrierattr_t +#define __NEED_pthread_mutex_t +#define __NEED_pthread_cond_t +#define __NEED_pthread_rwlock_t +#define __NEED_pthread_barrier_t +#define __NEED_pthread_spinlock_t +#define __NEED_pthread_key_t +#define __NEED_pthread_once_t +#define __NEED_size_t + +#include + +#include +#include + +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_CREATE_DETACHED 1 + +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_DEFAULT 0 +#define PTHREAD_MUTEX_RECURSIVE 1 +#define PTHREAD_MUTEX_ERRORCHECK 2 + +#define PTHREAD_MUTEX_STALLED 0 +#define PTHREAD_MUTEX_ROBUST 1 + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 + +#define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_EXPLICIT_SCHED 1 + +#define PTHREAD_SCOPE_SYSTEM 0 +#define PTHREAD_SCOPE_PROCESS 1 + +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + + +#define PTHREAD_MUTEX_INITIALIZER {{{0}}} +#define PTHREAD_RWLOCK_INITIALIZER {{{0}}} +#define PTHREAD_COND_INITIALIZER {{{0}}} +#define PTHREAD_ONCE_INIT 0 + + +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCEL_MASKED 2 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +#define PTHREAD_CANCELED ((void *)-1) + + +#define PTHREAD_BARRIER_SERIAL_THREAD (-1) + + +#define PTHREAD_NULL ((pthread_t)0) + + +int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict); +int pthread_detach(pthread_t); +_Noreturn void pthread_exit(void *); +int pthread_join(pthread_t, void **); + +#ifdef __GNUC__ +__attribute__((const)) +#endif +pthread_t pthread_self(void); + +int pthread_equal(pthread_t, pthread_t); +#ifndef __cplusplus +#define pthread_equal(x,y) ((x)==(y)) +#endif + +int pthread_setcancelstate(int, int *); +int pthread_setcanceltype(int, int *); +void pthread_testcancel(void); +int pthread_cancel(pthread_t); + +int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict); +int pthread_setschedparam(pthread_t, int, const struct sched_param *); +int pthread_setschedprio(pthread_t, int); + +int pthread_once(pthread_once_t *, void (*)(void)); + +int pthread_mutex_init(pthread_mutex_t *__restrict, const pthread_mutexattr_t *__restrict); +int pthread_mutex_lock(pthread_mutex_t *); +int pthread_mutex_unlock(pthread_mutex_t *); +int pthread_mutex_trylock(pthread_mutex_t *); +int pthread_mutex_timedlock(pthread_mutex_t *__restrict, const struct timespec *__restrict); +int pthread_mutex_destroy(pthread_mutex_t *); +int pthread_mutex_consistent(pthread_mutex_t *); + +int pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict, int *__restrict); +int pthread_mutex_setprioceiling(pthread_mutex_t *__restrict, int, int *__restrict); + +int pthread_cond_init(pthread_cond_t *__restrict, const pthread_condattr_t *__restrict); +int pthread_cond_destroy(pthread_cond_t *); +int pthread_cond_wait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict); +int pthread_cond_timedwait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict, const struct timespec *__restrict); +int pthread_cond_broadcast(pthread_cond_t *); +int pthread_cond_signal(pthread_cond_t *); + +int pthread_rwlock_init(pthread_rwlock_t *__restrict, const pthread_rwlockattr_t *__restrict); +int pthread_rwlock_destroy(pthread_rwlock_t *); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_tryrdlock(pthread_rwlock_t *); +int pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlock_trywrlock(pthread_rwlock_t *); +int pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict); +int pthread_rwlock_unlock(pthread_rwlock_t *); + +int pthread_spin_init(pthread_spinlock_t *, int); +int pthread_spin_destroy(pthread_spinlock_t *); +int pthread_spin_lock(pthread_spinlock_t *); +int pthread_spin_trylock(pthread_spinlock_t *); +int pthread_spin_unlock(pthread_spinlock_t *); + +int pthread_barrier_init(pthread_barrier_t *__restrict, const pthread_barrierattr_t *__restrict, unsigned); +int pthread_barrier_destroy(pthread_barrier_t *); +int pthread_barrier_wait(pthread_barrier_t *); + +int pthread_key_create(pthread_key_t *, void (*)(void *)); +int pthread_key_delete(pthread_key_t); +void *pthread_getspecific(pthread_key_t); +int pthread_setspecific(pthread_key_t, const void *); + +int pthread_attr_init(pthread_attr_t *); +int pthread_attr_destroy(pthread_attr_t *); + +int pthread_attr_getguardsize(const pthread_attr_t *__restrict, size_t *__restrict); +int pthread_attr_setguardsize(pthread_attr_t *, size_t); +int pthread_attr_getstacksize(const pthread_attr_t *__restrict, size_t *__restrict); +int pthread_attr_setstacksize(pthread_attr_t *, size_t); +int pthread_attr_getdetachstate(const pthread_attr_t *, int *); +int pthread_attr_setdetachstate(pthread_attr_t *, int); +int pthread_attr_getstack(const pthread_attr_t *__restrict, void **__restrict, size_t *__restrict); +int pthread_attr_setstack(pthread_attr_t *, void *, size_t); +int pthread_attr_getscope(const pthread_attr_t *__restrict, int *__restrict); +int pthread_attr_setscope(pthread_attr_t *, int); +int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict); +int pthread_attr_setschedpolicy(pthread_attr_t *, int); +int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict); +int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict); +int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict); +int pthread_attr_setinheritsched(pthread_attr_t *, int); + +int pthread_mutexattr_destroy(pthread_mutexattr_t *); +int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_getrobust(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict, int *__restrict); +int pthread_mutexattr_init(pthread_mutexattr_t *); +int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int); +int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int); +int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int); +int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int); +int pthread_mutexattr_settype(pthread_mutexattr_t *, int); + +int pthread_condattr_init(pthread_condattr_t *); +int pthread_condattr_destroy(pthread_condattr_t *); +int pthread_condattr_setclock(pthread_condattr_t *, clockid_t); +int pthread_condattr_setpshared(pthread_condattr_t *, int); +int pthread_condattr_getclock(const pthread_condattr_t *__restrict, clockid_t *__restrict); +int pthread_condattr_getpshared(const pthread_condattr_t *__restrict, int *__restrict); + +int pthread_rwlockattr_init(pthread_rwlockattr_t *); +int pthread_rwlockattr_destroy(pthread_rwlockattr_t *); +int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int); +int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict, int *__restrict); + +int pthread_barrierattr_destroy(pthread_barrierattr_t *); +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict, int *__restrict); +int pthread_barrierattr_init(pthread_barrierattr_t *); +int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); + +int pthread_atfork(void (*)(void), void (*)(void), void (*)(void)); + +int pthread_getconcurrency(void); +int pthread_setconcurrency(int); + +int pthread_getcpuclockid(pthread_t, clockid_t *); + +struct __ptcb { + void (*__f)(void *); + void *__x; + struct __ptcb *__next; +}; + +void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *); +void _pthread_cleanup_pop(struct __ptcb *, int); + +#define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x); +#define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0) + +#ifdef _GNU_SOURCE +struct cpu_set_t; +int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *); +int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *); +int pthread_getattr_np(pthread_t, pthread_attr_t *); +int pthread_setname_np(pthread_t, const char *); +int pthread_getattr_default_np(pthread_attr_t *); +int pthread_setattr_default_np(const pthread_attr_t *); +int pthread_tryjoin_np(pthread_t, void **); +int pthread_timedjoin_np(pthread_t, void **, const struct timespec *); +#endif + +#if _REDIR_TIME64 +__REDIR(pthread_mutex_timedlock, __pthread_mutex_timedlock_time64); +__REDIR(pthread_cond_timedwait, __pthread_cond_timedwait_time64); +__REDIR(pthread_rwlock_timedrdlock, __pthread_rwlock_timedrdlock_time64); +__REDIR(pthread_rwlock_timedwrlock, __pthread_rwlock_timedwrlock_time64); +#ifdef _GNU_SOURCE +__REDIR(pthread_timedjoin_np, __pthread_timedjoin_np_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/pty.h b/c/common/test/includes/standard-library/pty.h new file mode 100644 index 0000000000..db63853411 --- /dev/null +++ b/c/common/test/includes/standard-library/pty.h @@ -0,0 +1,18 @@ +#ifndef _PTY_H +#define _PTY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int openpty(int *, int *, char *, const struct termios *, const struct winsize *); +int forkpty(int *, char *, const struct termios *, const struct winsize *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/pwd.h b/c/common/test/includes/standard-library/pwd.h new file mode 100644 index 0000000000..4f470b558b --- /dev/null +++ b/c/common/test/includes/standard-library/pwd.h @@ -0,0 +1,50 @@ +#ifndef _PWD_H +#define _PWD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#define __NEED_uid_t +#define __NEED_gid_t + +#ifdef _GNU_SOURCE +#define __NEED_FILE +#endif + +#include + +struct passwd { + char *pw_name; + char *pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +}; + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +void setpwent (void); +void endpwent (void); +struct passwd *getpwent (void); +#endif + +struct passwd *getpwuid (uid_t); +struct passwd *getpwnam (const char *); +int getpwuid_r (uid_t, struct passwd *, char *, size_t, struct passwd **); +int getpwnam_r (const char *, struct passwd *, char *, size_t, struct passwd **); + +#ifdef _GNU_SOURCE +struct passwd *fgetpwent(FILE *); +int putpwent(const struct passwd *, FILE *); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/regex.h b/c/common/test/includes/standard-library/regex.h new file mode 100644 index 0000000000..dce217718f --- /dev/null +++ b/c/common/test/includes/standard-library/regex.h @@ -0,0 +1,62 @@ +#ifndef _REGEX_H +#define _REGEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_regoff_t +#define __NEED_size_t + +#include + +typedef struct re_pattern_buffer { + size_t re_nsub; + void *__opaque, *__padding[4]; + size_t __nsub2; + char __padding2; +} regex_t; + +typedef struct { + regoff_t rm_so; + regoff_t rm_eo; +} regmatch_t; + +#define REG_EXTENDED 1 +#define REG_ICASE 2 +#define REG_NEWLINE 4 +#define REG_NOSUB 8 + +#define REG_NOTBOL 1 +#define REG_NOTEOL 2 + +#define REG_OK 0 +#define REG_NOMATCH 1 +#define REG_BADPAT 2 +#define REG_ECOLLATE 3 +#define REG_ECTYPE 4 +#define REG_EESCAPE 5 +#define REG_ESUBREG 6 +#define REG_EBRACK 7 +#define REG_EPAREN 8 +#define REG_EBRACE 9 +#define REG_BADBR 10 +#define REG_ERANGE 11 +#define REG_ESPACE 12 +#define REG_BADRPT 13 + +#define REG_ENOSYS -1 + +int regcomp(regex_t *__restrict, const char *__restrict, int); +int regexec(const regex_t *__restrict, const char *__restrict, size_t, regmatch_t *__restrict, int); +void regfree(regex_t *); + +size_t regerror(int, const regex_t *__restrict, char *__restrict, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/resolv.h b/c/common/test/includes/standard-library/resolv.h new file mode 100644 index 0000000000..8b23ad66cc --- /dev/null +++ b/c/common/test/includes/standard-library/resolv.h @@ -0,0 +1,142 @@ +#ifndef _RESOLV_H +#define _RESOLV_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAXNS 3 +#define MAXDFLSRCH 3 +#define MAXDNSRCH 6 +#define LOCALDOMAINPARTS 2 + +#define RES_TIMEOUT 5 +#define MAXRESOLVSORT 10 +#define RES_MAXNDOTS 15 +#define RES_MAXRETRANS 30 +#define RES_MAXRETRY 5 +#define RES_DFLRETRY 2 +#define RES_MAXTIME 65535 + +/* unused; purely for broken apps */ +typedef struct __res_state { + int retrans; + int retry; + unsigned long options; + int nscount; + struct sockaddr_in nsaddr_list[MAXNS]; +# define nsaddr nsaddr_list[0] + unsigned short id; + char *dnsrch[MAXDNSRCH+1]; + char defdname[256]; + unsigned long pfcode; + unsigned ndots:4; + unsigned nsort:4; + unsigned ipv6_unavail:1; + unsigned unused:23; + struct { + struct in_addr addr; + uint32_t mask; + } sort_list[MAXRESOLVSORT]; + void *qhook; + void *rhook; + int res_h_errno; + int _vcsock; + unsigned _flags; + union { + char pad[52]; + struct { + uint16_t nscount; + uint16_t nsmap[MAXNS]; + int nssocks[MAXNS]; + uint16_t nscount6; + uint16_t nsinit; + struct sockaddr_in6 *nsaddrs[MAXNS]; + unsigned int _initstamp[2]; + } _ext; + } _u; +} *res_state; + +#define __RES 19960801 + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +struct res_sym { + int number; + char *name; + char *humanname; +}; + +#define RES_F_VC 0x00000001 +#define RES_F_CONN 0x00000002 +#define RES_F_EDNS0ERR 0x00000004 + +#define RES_EXHAUSTIVE 0x00000001 + +#define RES_INIT 0x00000001 +#define RES_DEBUG 0x00000002 +#define RES_AAONLY 0x00000004 +#define RES_USEVC 0x00000008 +#define RES_PRIMARY 0x00000010 +#define RES_IGNTC 0x00000020 +#define RES_RECURSE 0x00000040 +#define RES_DEFNAMES 0x00000080 +#define RES_STAYOPEN 0x00000100 +#define RES_DNSRCH 0x00000200 +#define RES_INSECURE1 0x00000400 +#define RES_INSECURE2 0x00000800 +#define RES_NOALIASES 0x00001000 +#define RES_USE_INET6 0x00002000 +#define RES_ROTATE 0x00004000 +#define RES_NOCHECKNAME 0x00008000 +#define RES_KEEPTSIG 0x00010000 +#define RES_BLAST 0x00020000 +#define RES_USEBSTRING 0x00040000 +#define RES_NOIP6DOTINT 0x00080000 +#define RES_USE_EDNS0 0x00100000 +#define RES_SNGLKUP 0x00200000 +#define RES_SNGLKUPREOP 0x00400000 +#define RES_USE_DNSSEC 0x00800000 + +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT) + +#define RES_PRF_STATS 0x00000001 +#define RES_PRF_UPDATE 0x00000002 +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 + +struct __res_state *__res_state(void); +#define _res (*__res_state()) + +int res_init(void); +int res_query(const char *, int, int, unsigned char *, int); +int res_querydomain(const char *, const char *, int, int, unsigned char *, int); +int res_search(const char *, int, int, unsigned char *, int); +int res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); +int res_send(const unsigned char *, int, unsigned char *, int); +int dn_comp(const char *, unsigned char *, int, unsigned char **, unsigned char **); +int dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); +int dn_skipname(const unsigned char *, const unsigned char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sched.h b/c/common/test/includes/standard-library/sched.h new file mode 100644 index 0000000000..fda4b48460 --- /dev/null +++ b/c/common/test/includes/standard-library/sched.h @@ -0,0 +1,148 @@ +#ifndef _SCHED_H +#define _SCHED_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_struct_timespec +#define __NEED_pid_t +#define __NEED_time_t + +#ifdef _GNU_SOURCE +#define __NEED_size_t +#endif + +#include + +struct sched_param { + int sched_priority; + int __reserved1; +#if _REDIR_TIME64 + long __reserved2[4]; +#else + struct { + time_t __reserved1; + long __reserved2; + } __reserved2[2]; +#endif + int __reserved3; +}; + +int sched_get_priority_max(int); +int sched_get_priority_min(int); +int sched_getparam(pid_t, struct sched_param *); +int sched_getscheduler(pid_t); +int sched_rr_get_interval(pid_t, struct timespec *); +int sched_setparam(pid_t, const struct sched_param *); +int sched_setscheduler(pid_t, int, const struct sched_param *); +int sched_yield(void); + +#define SCHED_OTHER 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#define SCHED_BATCH 3 +#define SCHED_IDLE 5 +#define SCHED_DEADLINE 6 +#define SCHED_RESET_ON_FORK 0x40000000 + +#ifdef _GNU_SOURCE +#define CSIGNAL 0x000000ff +#define CLONE_NEWTIME 0x00000080 +#define CLONE_VM 0x00000100 +#define CLONE_FS 0x00000200 +#define CLONE_FILES 0x00000400 +#define CLONE_SIGHAND 0x00000800 +#define CLONE_PIDFD 0x00001000 +#define CLONE_PTRACE 0x00002000 +#define CLONE_VFORK 0x00004000 +#define CLONE_PARENT 0x00008000 +#define CLONE_THREAD 0x00010000 +#define CLONE_NEWNS 0x00020000 +#define CLONE_SYSVSEM 0x00040000 +#define CLONE_SETTLS 0x00080000 +#define CLONE_PARENT_SETTID 0x00100000 +#define CLONE_CHILD_CLEARTID 0x00200000 +#define CLONE_DETACHED 0x00400000 +#define CLONE_UNTRACED 0x00800000 +#define CLONE_CHILD_SETTID 0x01000000 +#define CLONE_NEWCGROUP 0x02000000 +#define CLONE_NEWUTS 0x04000000 +#define CLONE_NEWIPC 0x08000000 +#define CLONE_NEWUSER 0x10000000 +#define CLONE_NEWPID 0x20000000 +#define CLONE_NEWNET 0x40000000 +#define CLONE_IO 0x80000000 +int clone (int (*)(void *), void *, int, void *, ...); +int unshare(int); +int setns(int, int); + +void *memcpy(void *__restrict, const void *__restrict, size_t); +int memcmp(const void *, const void *, size_t); +void *memset (void *, int, size_t); +void *calloc(size_t, size_t); +void free(void *); + +typedef struct cpu_set_t { unsigned long __bits[128/sizeof(long)]; } cpu_set_t; +int __sched_cpucount(size_t, const cpu_set_t *); +int sched_getcpu(void); +int sched_getaffinity(pid_t, size_t, cpu_set_t *); +int sched_setaffinity(pid_t, size_t, const cpu_set_t *); + +#define __CPU_op_S(i, size, set, op) ( (i)/8U >= (size) ? 0 : \ + (((unsigned long *)(set))[(i)/8/sizeof(long)] op (1UL<<((i)%(8*sizeof(long))))) ) + +#define CPU_SET_S(i, size, set) __CPU_op_S(i, size, set, |=) +#define CPU_CLR_S(i, size, set) __CPU_op_S(i, size, set, &=~) +#define CPU_ISSET_S(i, size, set) __CPU_op_S(i, size, set, &) + +#define __CPU_op_func_S(func, op) \ +static __inline void __CPU_##func##_S(size_t __size, cpu_set_t *__dest, \ + const cpu_set_t *__src1, const cpu_set_t *__src2) \ +{ \ + size_t __i; \ + for (__i=0; __i<__size/sizeof(long); __i++) \ + ((unsigned long *)__dest)[__i] = ((unsigned long *)__src1)[__i] \ + op ((unsigned long *)__src2)[__i] ; \ +} + +__CPU_op_func_S(AND, &) +__CPU_op_func_S(OR, |) +__CPU_op_func_S(XOR, ^) + +#define CPU_AND_S(a,b,c,d) __CPU_AND_S(a,b,c,d) +#define CPU_OR_S(a,b,c,d) __CPU_OR_S(a,b,c,d) +#define CPU_XOR_S(a,b,c,d) __CPU_XOR_S(a,b,c,d) + +#define CPU_COUNT_S(size,set) __sched_cpucount(size,set) +#define CPU_ZERO_S(size,set) memset(set,0,size) +#define CPU_EQUAL_S(size,set1,set2) (!memcmp(set1,set2,size)) + +#define CPU_ALLOC_SIZE(n) (sizeof(long) * ( (n)/(8*sizeof(long)) \ + + ((n)%(8*sizeof(long)) + 8*sizeof(long)-1)/(8*sizeof(long)) ) ) +#define CPU_ALLOC(n) ((cpu_set_t *)calloc(1,CPU_ALLOC_SIZE(n))) +#define CPU_FREE(set) free(set) + +#define CPU_SETSIZE 128 + +#define CPU_SET(i, set) CPU_SET_S(i,sizeof(cpu_set_t),set) +#define CPU_CLR(i, set) CPU_CLR_S(i,sizeof(cpu_set_t),set) +#define CPU_ISSET(i, set) CPU_ISSET_S(i,sizeof(cpu_set_t),set) +#define CPU_AND(d,s1,s2) CPU_AND_S(sizeof(cpu_set_t),d,s1,s2) +#define CPU_OR(d,s1,s2) CPU_OR_S(sizeof(cpu_set_t),d,s1,s2) +#define CPU_XOR(d,s1,s2) CPU_XOR_S(sizeof(cpu_set_t),d,s1,s2) +#define CPU_COUNT(set) CPU_COUNT_S(sizeof(cpu_set_t),set) +#define CPU_ZERO(set) CPU_ZERO_S(sizeof(cpu_set_t),set) +#define CPU_EQUAL(s1,s2) CPU_EQUAL_S(sizeof(cpu_set_t),s1,s2) + +#endif + +#if _REDIR_TIME64 +__REDIR(sched_rr_get_interval, __sched_rr_get_interval_time64); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/scsi/scsi.h b/c/common/test/includes/standard-library/scsi/scsi.h new file mode 100644 index 0000000000..8837f58756 --- /dev/null +++ b/c/common/test/includes/standard-library/scsi/scsi.h @@ -0,0 +1,150 @@ +#ifndef _SCSI_SCSI_H +#define _SCSI_SCSI_H + +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define READ_TOC 0x43 +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define MOVE_MEDIUM 0xa5 +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define WRITE_VERIFY_12 0xae +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea +#define GOOD 0x00 +#define CHECK_CONDITION 0x01 +#define CONDITION_GOOD 0x02 +#define BUSY 0x04 +#define INTERMEDIATE_GOOD 0x08 +#define INTERMEDIATE_C_GOOD 0x0a +#define RESERVATION_CONFLICT 0x0c +#define COMMAND_TERMINATED 0x11 +#define QUEUE_FULL 0x14 +#define STATUS_MASK 0x3e +#define NO_SENSE 0x00 +#define RECOVERED_ERROR 0x01 +#define NOT_READY 0x02 +#define MEDIUM_ERROR 0x03 +#define HARDWARE_ERROR 0x04 +#define ILLEGAL_REQUEST 0x05 +#define UNIT_ATTENTION 0x06 +#define DATA_PROTECT 0x07 +#define BLANK_CHECK 0x08 +#define COPY_ABORTED 0x0a +#define ABORTED_COMMAND 0x0b +#define VOLUME_OVERFLOW 0x0d +#define MISCOMPARE 0x0e +#define TYPE_DISK 0x00 +#define TYPE_TAPE 0x01 +#define TYPE_PROCESSOR 0x03 +#define TYPE_WORM 0x04 +#define TYPE_ROM 0x05 +#define TYPE_SCANNER 0x06 +#define TYPE_MOD 0x07 +#define TYPE_MEDIUM_CHANGER 0x08 +#define TYPE_ENCLOSURE 0x0d +#define TYPE_NO_LUN 0x7f +#define COMMAND_COMPLETE 0x00 +#define EXTENDED_MESSAGE 0x01 +#define EXTENDED_MODIFY_DATA_POINTER 0x00 +#define EXTENDED_SDTR 0x01 +#define EXTENDED_EXTENDED_IDENTIFY 0x02 +#define EXTENDED_WDTR 0x03 +#define SAVE_POINTERS 0x02 +#define RESTORE_POINTERS 0x03 +#define DISCONNECT 0x04 +#define INITIATOR_ERROR 0x05 +#define ABORT 0x06 +#define MESSAGE_REJECT 0x07 +#define NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define LINKED_CMD_COMPLETE 0x0a +#define LINKED_FLG_CMD_COMPLETE 0x0b +#define BUS_DEVICE_RESET 0x0c +#define INITIATE_RECOVERY 0x0f +#define RELEASE_RECOVERY 0x10 +#define SIMPLE_QUEUE_TAG 0x20 +#define HEAD_OF_QUEUE_TAG 0x21 +#define ORDERED_QUEUE_TAG 0x22 +#define SCSI_IOCTL_GET_IDLUN 0x5382 +#define SCSI_IOCTL_TAGGED_ENABLE 0x5383 +#define SCSI_IOCTL_TAGGED_DISABLE 0x5384 +#define SCSI_IOCTL_PROBE_HOST 0x5385 +#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386 + +struct ccs_modesel_head { + unsigned char _r1; + unsigned char medium; + unsigned char _r2; + unsigned char block_desc_length; + unsigned char density; + unsigned char number_blocks_hi; + unsigned char number_blocks_med; + unsigned char number_blocks_lo; + unsigned char _r3; + unsigned char block_length_hi; + unsigned char block_length_med; + unsigned char block_length_lo; +}; + +#endif + diff --git a/c/common/test/includes/standard-library/scsi/scsi_ioctl.h b/c/common/test/includes/standard-library/scsi/scsi_ioctl.h new file mode 100644 index 0000000000..22df7feffa --- /dev/null +++ b/c/common/test/includes/standard-library/scsi/scsi_ioctl.h @@ -0,0 +1,11 @@ +#ifndef _SCSI_IOCTL_H +#define _SCSI_IOCTL_H +#define SCSI_IOCTL_SEND_COMMAND 1 +#define SCSI_IOCTL_TEST_UNIT_READY 2 +#define SCSI_IOCTL_BENCHMARK_COMMAND 3 +#define SCSI_IOCTL_SYNC 4 +#define SCSI_IOCTL_START_UNIT 5 +#define SCSI_IOCTL_STOP_UNIT 6 +#define SCSI_IOCTL_DOORLOCK 0x5380 +#define SCSI_IOCTL_DOORUNLOCK 0x5381 +#endif diff --git a/c/common/test/includes/standard-library/scsi/sg.h b/c/common/test/includes/standard-library/scsi/sg.h new file mode 100644 index 0000000000..a7ac247e3f --- /dev/null +++ b/c/common/test/includes/standard-library/scsi/sg.h @@ -0,0 +1,129 @@ +#ifndef _SCSI_SG_H +#define _SCSI_SG_H + +#define SG_DXFER_NONE -1 +#define SG_DXFER_TO_DEV -2 +#define SG_DXFER_FROM_DEV -3 +#define SG_DXFER_TO_FROM_DEV -4 +#define SG_FLAG_DIRECT_IO 1 +#define SG_FLAG_LUN_INHIBIT 2 +#define SG_FLAG_NO_DXFER 0x10000 +#define SG_INFO_OK_MASK 0x1 +#define SG_INFO_OK 0x0 +#define SG_INFO_CHECK 0x1 +#define SG_INFO_DIRECT_IO_MASK 0x6 +#define SG_INFO_INDIRECT_IO 0x0 +#define SG_INFO_DIRECT_IO 0x2 +#define SG_INFO_MIXED_IO 0x4 +#define SG_EMULATED_HOST 0x2203 +#define SG_SET_TRANSFORM 0x2204 +#define SG_GET_TRANSFORM 0x2205 +#define SG_SET_RESERVED_SIZE 0x2275 +#define SG_GET_RESERVED_SIZE 0x2272 +#define SG_GET_SCSI_ID 0x2276 +#define SG_SET_FORCE_LOW_DMA 0x2279 +#define SG_GET_LOW_DMA 0x227a +#define SG_SET_FORCE_PACK_ID 0x227b +#define SG_GET_PACK_ID 0x227c +#define SG_GET_NUM_WAITING 0x227d +#define SG_GET_SG_TABLESIZE 0x227F +#define SG_GET_VERSION_NUM 0x2282 +#define SG_SCSI_RESET 0x2284 +#define SG_SCSI_RESET_NOTHING 0 +#define SG_SCSI_RESET_DEVICE 1 +#define SG_SCSI_RESET_BUS 2 +#define SG_SCSI_RESET_HOST 3 +#define SG_IO 0x2285 +#define SG_GET_REQUEST_TABLE 0x2286 +#define SG_SET_KEEP_ORPHAN 0x2287 +#define SG_GET_KEEP_ORPHAN 0x2288 +#define SG_SCATTER_SZ (8 * 4096) +#define SG_DEFAULT_RETRIES 1 +#define SG_DEF_FORCE_LOW_DMA 0 +#define SG_DEF_FORCE_PACK_ID 0 +#define SG_DEF_KEEP_ORPHAN 0 +#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ +#define SG_MAX_QUEUE 16 +#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE +#define SG_MAX_SENSE 16 +#define SG_SET_TIMEOUT 0x2201 +#define SG_GET_TIMEOUT 0x2202 +#define SG_GET_COMMAND_Q 0x2270 +#define SG_SET_COMMAND_Q 0x2271 +#define SG_SET_DEBUG 0x227e +#define SG_NEXT_CMD_LEN 0x2283 +#define SG_DEFAULT_TIMEOUT (60*100) /* 60*HZ */ +#define SG_DEF_COMMAND_Q 0 +#define SG_DEF_UNDERRUN_FLAG 0 + +typedef struct sg_iovec { + void *iov_base; + unsigned long iov_len; +} sg_iovec_t; + +typedef struct sg_io_hdr { + int interface_id; + int dxfer_direction; + unsigned char cmd_len; + unsigned char mx_sb_len; + unsigned short iovec_count; + unsigned dxfer_len; + void *dxferp; + unsigned char *cmdp; + unsigned char *sbp; + unsigned timeout; + unsigned flags; + int pack_id; + void *usr_ptr; + unsigned char status; + unsigned char masked_status; + unsigned char msg_status; + unsigned char sb_len_wr; + unsigned short host_status; + unsigned short driver_status; + int resid; + unsigned int duration; + unsigned int info; +} sg_io_hdr_t; + +struct sg_scsi_id { + int host_no; + int channel; + int scsi_id; + int lun; + int scsi_type; + short h_cmd_per_lun; + short d_queue_depth; + int unused[2]; +}; + +typedef struct sg_req_info { + char req_state; + char orphan; + char sg_io_owned; + char problem; + int pack_id; + void *usr_ptr; + unsigned duration; + int unused; +} sg_req_info_t; + +typedef struct sg_io_hdr Sg_io_hdr; +typedef struct sg_io_vec Sg_io_vec; +typedef struct sg_scsi_id Sg_scsi_id; +typedef struct sg_req_info Sg_req_info; + +struct sg_header { + int pack_len; + int reply_len; + int pack_id; + int result; + unsigned twelve_byte:1; + unsigned target_status:5; + unsigned host_status:8; + unsigned driver_status:8; + unsigned other_flags:10; + unsigned char sense_buffer[SG_MAX_SENSE]; +}; + +#endif diff --git a/c/common/test/includes/standard-library/search.h b/c/common/test/includes/standard-library/search.h new file mode 100644 index 0000000000..02e407e3c2 --- /dev/null +++ b/c/common/test/includes/standard-library/search.h @@ -0,0 +1,63 @@ +#ifndef _SEARCH_H +#define _SEARCH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#include + +typedef enum { FIND, ENTER } ACTION; +typedef enum { preorder, postorder, endorder, leaf } VISIT; + +typedef struct entry { + char *key; + void *data; +} ENTRY; + +int hcreate(size_t); +void hdestroy(void); +ENTRY *hsearch(ENTRY, ACTION); + +#ifdef _GNU_SOURCE +struct hsearch_data { + struct __tab *__tab; + unsigned int __unused1; + unsigned int __unused2; +}; + +int hcreate_r(size_t, struct hsearch_data *); +void hdestroy_r(struct hsearch_data *); +int hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *); +#endif + +void insque(void *, void *); +void remque(void *); + +void *lsearch(const void *, void *, size_t *, size_t, + int (*)(const void *, const void *)); +void *lfind(const void *, const void *, size_t *, size_t, + int (*)(const void *, const void *)); + +void *tdelete(const void *__restrict, void **__restrict, int(*)(const void *, const void *)); +void *tfind(const void *, void *const *, int(*)(const void *, const void *)); +void *tsearch(const void *, void **, int (*)(const void *, const void *)); +void twalk(const void *, void (*)(const void *, VISIT, int)); + +#ifdef _GNU_SOURCE +struct qelem { + struct qelem *q_forw, *q_back; + char q_data[1]; +}; + +void tdestroy(void *, void (*)(void *)); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/semaphore.h b/c/common/test/includes/standard-library/semaphore.h new file mode 100644 index 0000000000..3690f49609 --- /dev/null +++ b/c/common/test/includes/standard-library/semaphore.h @@ -0,0 +1,39 @@ +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_time_t +#define __NEED_struct_timespec +#include + +#include + +#define SEM_FAILED ((sem_t *)0) + +typedef struct { + volatile int __val[4*sizeof(long)/sizeof(int)]; +} sem_t; + +int sem_close(sem_t *); +int sem_destroy(sem_t *); +int sem_getvalue(sem_t *__restrict, int *__restrict); +int sem_init(sem_t *, int, unsigned); +sem_t *sem_open(const char *, int, ...); +int sem_post(sem_t *); +int sem_timedwait(sem_t *__restrict, const struct timespec *__restrict); +int sem_trywait(sem_t *); +int sem_unlink(const char *); +int sem_wait(sem_t *); + +#if _REDIR_TIME64 +__REDIR(sem_timedwait, __sem_timedwait_time64); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/setjmp.h b/c/common/test/includes/standard-library/setjmp.h new file mode 100644 index 0000000000..2d43abf84f --- /dev/null +++ b/c/common/test/includes/standard-library/setjmp.h @@ -0,0 +1,41 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +typedef struct __jmp_buf_tag { + __jmp_buf __jb; + unsigned long __fl; + unsigned long __ss[128/sizeof(long)]; +} jmp_buf[1]; + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +typedef jmp_buf sigjmp_buf; +int sigsetjmp (sigjmp_buf, int); +_Noreturn void siglongjmp (sigjmp_buf, int); +#endif + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +int _setjmp (jmp_buf); +_Noreturn void _longjmp (jmp_buf, int); +#endif + +int setjmp (jmp_buf); +_Noreturn void longjmp (jmp_buf, int); + +#define setjmp setjmp + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/shadow.h b/c/common/test/includes/standard-library/shadow.h new file mode 100644 index 0000000000..2b1be413f3 --- /dev/null +++ b/c/common/test/includes/standard-library/shadow.h @@ -0,0 +1,44 @@ +#ifndef _SHADOW_H +#define _SHADOW_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_FILE +#define __NEED_size_t + +#include + +#define SHADOW "/etc/shadow" + +struct spwd { + char *sp_namp; + char *sp_pwdp; + long sp_lstchg; + long sp_min; + long sp_max; + long sp_warn; + long sp_inact; + long sp_expire; + unsigned long sp_flag; +}; + +void setspent(void); +void endspent(void); +struct spwd *getspent(void); +struct spwd *fgetspent(FILE *); +struct spwd *sgetspent(const char *); +int putspent(const struct spwd *, FILE *); + +struct spwd *getspnam(const char *); +int getspnam_r(const char *, struct spwd *, char *, size_t, struct spwd **); + +int lckpwdf(void); +int ulckpwdf(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/signal.h b/c/common/test/includes/standard-library/signal.h new file mode 100644 index 0000000000..9ed929e4f2 --- /dev/null +++ b/c/common/test/includes/standard-library/signal.h @@ -0,0 +1,296 @@ +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) + +#ifdef _GNU_SOURCE +#define __ucontext ucontext +#endif + +#define __NEED_size_t +#define __NEED_pid_t +#define __NEED_uid_t +#define __NEED_struct_timespec +#define __NEED_pthread_t +#define __NEED_pthread_attr_t +#define __NEED_time_t +#define __NEED_clock_t +#define __NEED_sigset_t + +#include + +#define SIG_BLOCK 0 +#define SIG_UNBLOCK 1 +#define SIG_SETMASK 2 + +#define SI_ASYNCNL (-60) +#define SI_TKILL (-6) +#define SI_SIGIO (-5) +#define SI_ASYNCIO (-4) +#define SI_MESGQ (-3) +#define SI_TIMER (-2) +#define SI_QUEUE (-1) +#define SI_USER 0 +#define SI_KERNEL 128 + +typedef struct sigaltstack stack_t; + +#endif + +#include + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) + +#define SIG_HOLD ((void (*)(int)) 2) + +#define FPE_INTDIV 1 +#define FPE_INTOVF 2 +#define FPE_FLTDIV 3 +#define FPE_FLTOVF 4 +#define FPE_FLTUND 5 +#define FPE_FLTRES 6 +#define FPE_FLTINV 7 +#define FPE_FLTSUB 8 + +#define ILL_ILLOPC 1 +#define ILL_ILLOPN 2 +#define ILL_ILLADR 3 +#define ILL_ILLTRP 4 +#define ILL_PRVOPC 5 +#define ILL_PRVREG 6 +#define ILL_COPROC 7 +#define ILL_BADSTK 8 + +#define SEGV_MAPERR 1 +#define SEGV_ACCERR 2 +#define SEGV_BNDERR 3 +#define SEGV_PKUERR 4 + +#define BUS_ADRALN 1 +#define BUS_ADRERR 2 +#define BUS_OBJERR 3 +#define BUS_MCEERR_AR 4 +#define BUS_MCEERR_AO 5 + +#define CLD_EXITED 1 +#define CLD_KILLED 2 +#define CLD_DUMPED 3 +#define CLD_TRAPPED 4 +#define CLD_STOPPED 5 +#define CLD_CONTINUED 6 + +union sigval { + int sival_int; + void *sival_ptr; +}; + +typedef struct { +#ifdef __SI_SWAP_ERRNO_CODE + int si_signo, si_code, si_errno; +#else + int si_signo, si_errno, si_code; +#endif + union { + char __pad[128 - 2*sizeof(int) - sizeof(long)]; + struct { + union { + struct { + pid_t si_pid; + uid_t si_uid; + } __piduid; + struct { + int si_timerid; + int si_overrun; + } __timer; + } __first; + union { + union sigval si_value; + struct { + int si_status; + clock_t si_utime, si_stime; + } __sigchld; + } __second; + } __si_common; + struct { + void *si_addr; + short si_addr_lsb; + union { + struct { + void *si_lower; + void *si_upper; + } __addr_bnd; + unsigned si_pkey; + } __first; + } __sigfault; + struct { + long si_band; + int si_fd; + } __sigpoll; + struct { + void *si_call_addr; + int si_syscall; + unsigned si_arch; + } __sigsys; + } __si_fields; +} siginfo_t; +#define si_pid __si_fields.__si_common.__first.__piduid.si_pid +#define si_uid __si_fields.__si_common.__first.__piduid.si_uid +#define si_status __si_fields.__si_common.__second.__sigchld.si_status +#define si_utime __si_fields.__si_common.__second.__sigchld.si_utime +#define si_stime __si_fields.__si_common.__second.__sigchld.si_stime +#define si_value __si_fields.__si_common.__second.si_value +#define si_addr __si_fields.__sigfault.si_addr +#define si_addr_lsb __si_fields.__sigfault.si_addr_lsb +#define si_lower __si_fields.__sigfault.__first.__addr_bnd.si_lower +#define si_upper __si_fields.__sigfault.__first.__addr_bnd.si_upper +#define si_pkey __si_fields.__sigfault.__first.si_pkey +#define si_band __si_fields.__sigpoll.si_band +#define si_fd __si_fields.__sigpoll.si_fd +#define si_timerid __si_fields.__si_common.__first.__timer.si_timerid +#define si_overrun __si_fields.__si_common.__first.__timer.si_overrun +#define si_ptr si_value.sival_ptr +#define si_int si_value.sival_int +#define si_call_addr __si_fields.__sigsys.si_call_addr +#define si_syscall __si_fields.__sigsys.si_syscall +#define si_arch __si_fields.__sigsys.si_arch + +struct sigaction { + union { + void (*sa_handler)(int); + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sa_handler; + sigset_t sa_mask; + int sa_flags; + void (*sa_restorer)(void); +}; +#define sa_handler __sa_handler.sa_handler +#define sa_sigaction __sa_handler.sa_sigaction + +struct sigevent { + union sigval sigev_value; + int sigev_signo; + int sigev_notify; + union { + char __pad[64 - 2*sizeof(int) - sizeof(union sigval)]; + pid_t sigev_notify_thread_id; + struct { + void (*sigev_notify_function)(union sigval); + pthread_attr_t *sigev_notify_attributes; + } __sev_thread; + } __sev_fields; +}; + +#define sigev_notify_thread_id __sev_fields.sigev_notify_thread_id +#define sigev_notify_function __sev_fields.__sev_thread.sigev_notify_function +#define sigev_notify_attributes __sev_fields.__sev_thread.sigev_notify_attributes + +#define SIGEV_SIGNAL 0 +#define SIGEV_NONE 1 +#define SIGEV_THREAD 2 +#define SIGEV_THREAD_ID 4 + +int __libc_current_sigrtmin(void); +int __libc_current_sigrtmax(void); + +#define SIGRTMIN (__libc_current_sigrtmin()) +#define SIGRTMAX (__libc_current_sigrtmax()) + +int kill(pid_t, int); + +int sigemptyset(sigset_t *); +int sigfillset(sigset_t *); +int sigaddset(sigset_t *, int); +int sigdelset(sigset_t *, int); +int sigismember(const sigset_t *, int); + +int sigprocmask(int, const sigset_t *__restrict, sigset_t *__restrict); +int sigsuspend(const sigset_t *); +int sigaction(int, const struct sigaction *__restrict, struct sigaction *__restrict); +int sigpending(sigset_t *); +int sigwait(const sigset_t *__restrict, int *__restrict); +int sigwaitinfo(const sigset_t *__restrict, siginfo_t *__restrict); +int sigtimedwait(const sigset_t *__restrict, siginfo_t *__restrict, const struct timespec *__restrict); +int sigqueue(pid_t, int, union sigval); + +int pthread_sigmask(int, const sigset_t *__restrict, sigset_t *__restrict); +int pthread_kill(pthread_t, int); + +void psiginfo(const siginfo_t *, const char *); +void psignal(int, const char *); + +#endif + +#if defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +int killpg(pid_t, int); +int sigaltstack(const stack_t *__restrict, stack_t *__restrict); +int sighold(int); +int sigignore(int); +int siginterrupt(int, int); +int sigpause(int); +int sigrelse(int); +void (*sigset(int, void (*)(int)))(int); +#define TRAP_BRKPT 1 +#define TRAP_TRACE 2 +#define TRAP_BRANCH 3 +#define TRAP_HWBKPT 4 +#define TRAP_UNK 5 +#define POLL_IN 1 +#define POLL_OUT 2 +#define POLL_MSG 3 +#define POLL_ERR 4 +#define POLL_PRI 5 +#define POLL_HUP 6 +#define SS_ONSTACK 1 +#define SS_DISABLE 2 +#define SS_AUTODISARM (1U << 31) +#define SS_FLAG_BITS SS_AUTODISARM +#endif + +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define NSIG _NSIG +typedef void (*sig_t)(int); +#endif + +#ifdef _GNU_SOURCE +typedef void (*sighandler_t)(int); +void (*bsd_signal(int, void (*)(int)))(int); +int sigisemptyset(const sigset_t *); +int sigorset (sigset_t *, const sigset_t *, const sigset_t *); +int sigandset(sigset_t *, const sigset_t *, const sigset_t *); + +#define SA_NOMASK SA_NODEFER +#define SA_ONESHOT SA_RESETHAND +#endif + +#define SIG_ERR ((void (*)(int))-1) +#define SIG_DFL ((void (*)(int)) 0) +#define SIG_IGN ((void (*)(int)) 1) + +typedef int sig_atomic_t; + +void (*signal(int, void (*)(int)))(int); +int raise(int); + +#if _REDIR_TIME64 +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +__REDIR(sigtimedwait, __sigtimedwait_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/spawn.h b/c/common/test/includes/standard-library/spawn.h new file mode 100644 index 0000000000..8eb73e003a --- /dev/null +++ b/c/common/test/includes/standard-library/spawn.h @@ -0,0 +1,83 @@ +#ifndef _SPAWN_H +#define _SPAWN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_mode_t +#define __NEED_pid_t +#define __NEED_sigset_t + +#include + +struct sched_param; + +#define POSIX_SPAWN_RESETIDS 1 +#define POSIX_SPAWN_SETPGROUP 2 +#define POSIX_SPAWN_SETSIGDEF 4 +#define POSIX_SPAWN_SETSIGMASK 8 +#define POSIX_SPAWN_SETSCHEDPARAM 16 +#define POSIX_SPAWN_SETSCHEDULER 32 +#define POSIX_SPAWN_USEVFORK 64 +#define POSIX_SPAWN_SETSID 128 + +typedef struct { + int __flags; + pid_t __pgrp; + sigset_t __def, __mask; + int __prio, __pol; + void *__fn; + char __pad[64-sizeof(void *)]; +} posix_spawnattr_t; + +typedef struct { + int __pad0[2]; + void *__actions; + int __pad[16]; +} posix_spawn_file_actions_t; + +int posix_spawn(pid_t *__restrict, const char *__restrict, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *__restrict, char *const *__restrict, char *const *__restrict); +int posix_spawnp(pid_t *__restrict, const char *__restrict, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *__restrict, char *const *__restrict, char *const *__restrict); + +int posix_spawnattr_init(posix_spawnattr_t *); +int posix_spawnattr_destroy(posix_spawnattr_t *); + +int posix_spawnattr_setflags(posix_spawnattr_t *, short); +int posix_spawnattr_getflags(const posix_spawnattr_t *__restrict, short *__restrict); + +int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t); +int posix_spawnattr_getpgroup(const posix_spawnattr_t *__restrict, pid_t *__restrict); + +int posix_spawnattr_setsigmask(posix_spawnattr_t *__restrict, const sigset_t *__restrict); +int posix_spawnattr_getsigmask(const posix_spawnattr_t *__restrict, sigset_t *__restrict); + +int posix_spawnattr_setsigdefault(posix_spawnattr_t *__restrict, const sigset_t *__restrict); +int posix_spawnattr_getsigdefault(const posix_spawnattr_t *__restrict, sigset_t *__restrict); + +int posix_spawnattr_setschedparam(posix_spawnattr_t *__restrict, const struct sched_param *__restrict); +int posix_spawnattr_getschedparam(const posix_spawnattr_t *__restrict, struct sched_param *__restrict); +int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int); +int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *__restrict, int *__restrict); + +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *); + +int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *__restrict, int, const char *__restrict, int, mode_t); +int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int); +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int); + +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *__restrict, const char *__restrict); +int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *, int); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdalign.h b/c/common/test/includes/standard-library/stdalign.h new file mode 100644 index 0000000000..2cc94be3f6 --- /dev/null +++ b/c/common/test/includes/standard-library/stdalign.h @@ -0,0 +1,20 @@ +#ifndef _STDALIGN_H +#define _STDALIGN_H + +#ifndef __cplusplus + +/* this whole header only works in C11 or with compiler extensions */ +#if __STDC_VERSION__ < 201112L && defined( __GNUC__) +#define _Alignas(t) __attribute__((__aligned__(t))) +#define _Alignof(t) __alignof__(t) +#endif + +#define alignas _Alignas +#define alignof _Alignof + +#endif + +#define __alignas_is_defined 1 +#define __alignof_is_defined 1 + +#endif diff --git a/c/common/test/includes/standard-library/stdarg.h b/c/common/test/includes/standard-library/stdarg.h new file mode 100644 index 0000000000..3256f80500 --- /dev/null +++ b/c/common/test/includes/standard-library/stdarg.h @@ -0,0 +1,21 @@ +#ifndef _STDARG_H +#define _STDARG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_va_list + +#include + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_copy(d,s) __builtin_va_copy(d,s) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdbool.h b/c/common/test/includes/standard-library/stdbool.h new file mode 100644 index 0000000000..a9d7ab7878 --- /dev/null +++ b/c/common/test/includes/standard-library/stdbool.h @@ -0,0 +1,14 @@ +#ifndef _STDBOOL_H +#define _STDBOOL_H + +#ifndef __cplusplus + +#define true 1 +#define false 0 +#define bool _Bool + +#endif + +#define __bool_true_false_are_defined 1 + +#endif diff --git a/c/common/test/includes/standard-library/stdc-predef.h b/c/common/test/includes/standard-library/stdc-predef.h new file mode 100644 index 0000000000..f8cd4b8911 --- /dev/null +++ b/c/common/test/includes/standard-library/stdc-predef.h @@ -0,0 +1,10 @@ +#ifndef _STDC_PREDEF_H +#define _STDC_PREDEF_H + +#define __STDC_ISO_10646__ 201206L + +#if !defined(__GCC_IEC_559) || __GCC_IEC_559 > 0 +#define __STDC_IEC_559__ 1 +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stddef.h b/c/common/test/includes/standard-library/stddef.h new file mode 100644 index 0000000000..bd75385350 --- /dev/null +++ b/c/common/test/includes/standard-library/stddef.h @@ -0,0 +1,25 @@ +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#define __NEED_ptrdiff_t +#define __NEED_size_t +#define __NEED_wchar_t +#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L +#define __NEED_max_align_t +#endif + +#include + +#if __GNUC__ > 3 +#define offsetof(type, member) __builtin_offsetof(type, member) +#else +#define offsetof(type, member) ((size_t)( (char *)&(((type *)0)->member) - (char *)0 )) +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdint.h b/c/common/test/includes/standard-library/stdint.h new file mode 100644 index 0000000000..a2968197db --- /dev/null +++ b/c/common/test/includes/standard-library/stdint.h @@ -0,0 +1,117 @@ +#ifndef _STDINT_H +#define _STDINT_H + +#define __NEED_int8_t +#define __NEED_int16_t +#define __NEED_int32_t +#define __NEED_int64_t + +#define __NEED_uint8_t +#define __NEED_uint16_t +#define __NEED_uint32_t +#define __NEED_uint64_t + +#define __NEED_intptr_t +#define __NEED_uintptr_t + +#define __NEED_intmax_t +#define __NEED_uintmax_t + +#include + +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +#define INT8_MIN (-1-0x7f) +#define INT16_MIN (-1-0x7fff) +#define INT32_MIN (-1-0x7fffffff) +#define INT64_MIN (-1-0x7fffffffffffffff) + +#define INT8_MAX (0x7f) +#define INT16_MAX (0x7fff) +#define INT32_MAX (0x7fffffff) +#define INT64_MAX (0x7fffffffffffffff) + +#define UINT8_MAX (0xff) +#define UINT16_MAX (0xffff) +#define UINT32_MAX (0xffffffffu) +#define UINT64_MAX (0xffffffffffffffffu) + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define WINT_MIN 0U +#define WINT_MAX UINT32_MAX + +#if L'\0'-1 > 0 +#define WCHAR_MAX (0xffffffffu+L'\0') +#define WCHAR_MIN (0+L'\0') +#else +#define WCHAR_MAX (0x7fffffff+L'\0') +#define WCHAR_MIN (-1-0x7fffffff+L'\0') +#endif + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#include + +#define INT8_C(c) c +#define INT16_C(c) c +#define INT32_C(c) c + +#define UINT8_C(c) c +#define UINT16_C(c) c +#define UINT32_C(c) c ## U + +#if UINTPTR_MAX == UINT64_MAX +#define INT64_C(c) c ## L +#define UINT64_C(c) c ## UL +#define INTMAX_C(c) c ## L +#define UINTMAX_C(c) c ## UL +#else +#define INT64_C(c) c ## LL +#define UINT64_C(c) c ## ULL +#define INTMAX_C(c) c ## LL +#define UINTMAX_C(c) c ## ULL +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdio.h b/c/common/test/includes/standard-library/stdio.h new file mode 100644 index 0000000000..3604198c3e --- /dev/null +++ b/c/common/test/includes/standard-library/stdio.h @@ -0,0 +1,222 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_FILE +#define __NEED___isoc_va_list +#define __NEED_size_t + +#if __STDC_VERSION__ < 201112L +#define __NEED_struct__IO_FILE +#endif + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +#define __NEED_ssize_t +#define __NEED_off_t +#define __NEED_va_list +#endif + +#include + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#undef EOF +#define EOF (-1) + +#undef SEEK_SET +#undef SEEK_CUR +#undef SEEK_END +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#define _IOFBF 0 +#define _IOLBF 1 +#define _IONBF 2 + +#define BUFSIZ 1024 +#define FILENAME_MAX 4096 +#define FOPEN_MAX 1000 +#define TMP_MAX 10000 +#define L_tmpnam 20 + +typedef union _G_fpos64_t { + char __opaque[16]; + long long __lldata; + double __align; +} fpos_t; + +extern FILE *const stdin; +extern FILE *const stdout; +extern FILE *const stderr; + +#define stdin (stdin) +#define stdout (stdout) +#define stderr (stderr) + +FILE *fopen(const char *__restrict, const char *__restrict); +FILE *freopen(const char *__restrict, const char *__restrict, FILE *__restrict); +int fclose(FILE *); + +int remove(const char *); +int rename(const char *, const char *); + +int feof(FILE *); +int ferror(FILE *); +int fflush(FILE *); +void clearerr(FILE *); + +int fseek(FILE *, long, int); +long ftell(FILE *); +void rewind(FILE *); + +int fgetpos(FILE *__restrict, fpos_t *__restrict); +int fsetpos(FILE *, const fpos_t *); + +size_t fread(void *__restrict, size_t, size_t, FILE *__restrict); +size_t fwrite(const void *__restrict, size_t, size_t, FILE *__restrict); + +int fgetc(FILE *); +int getc(FILE *); +int getchar(void); +int ungetc(int, FILE *); + +int fputc(int, FILE *); +int putc(int, FILE *); +int putchar(int); + +char *fgets(char *__restrict, int, FILE *__restrict); +#if __STDC_VERSION__ < 201112L +char *gets(char *); +#endif + +int fputs(const char *__restrict, FILE *__restrict); +int puts(const char *); + +int printf(const char *__restrict, ...); +int fprintf(FILE *__restrict, const char *__restrict, ...); +int sprintf(char *__restrict, const char *__restrict, ...); +int snprintf(char *__restrict, size_t, const char *__restrict, ...); + +int vprintf(const char *__restrict, __isoc_va_list); +int vfprintf(FILE *__restrict, const char *__restrict, __isoc_va_list); +int vsprintf(char *__restrict, const char *__restrict, __isoc_va_list); +int vsnprintf(char *__restrict, size_t, const char *__restrict, __isoc_va_list); + +int scanf(const char *__restrict, ...); +int fscanf(FILE *__restrict, const char *__restrict, ...); +int sscanf(const char *__restrict, const char *__restrict, ...); +int vscanf(const char *__restrict, __isoc_va_list); +int vfscanf(FILE *__restrict, const char *__restrict, __isoc_va_list); +int vsscanf(const char *__restrict, const char *__restrict, __isoc_va_list); + +void perror(const char *); + +int setvbuf(FILE *__restrict, char *__restrict, int, size_t); +void setbuf(FILE *__restrict, char *__restrict); + +char *tmpnam(char *); +FILE *tmpfile(void); + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +FILE *fmemopen(void *__restrict, size_t, const char *__restrict); +FILE *open_memstream(char **, size_t *); +FILE *fdopen(int, const char *); +FILE *popen(const char *, const char *); +int pclose(FILE *); +int fileno(FILE *); +int fseeko(FILE *, off_t, int); +off_t ftello(FILE *); +int dprintf(int, const char *__restrict, ...); +int vdprintf(int, const char *__restrict, __isoc_va_list); +void flockfile(FILE *); +int ftrylockfile(FILE *); +void funlockfile(FILE *); +int getc_unlocked(FILE *); +int getchar_unlocked(void); +int putc_unlocked(int, FILE *); +int putchar_unlocked(int); +ssize_t getdelim(char **__restrict, size_t *__restrict, int, FILE *__restrict); +ssize_t getline(char **__restrict, size_t *__restrict, FILE *__restrict); +int renameat(int, const char *, int, const char *); +char *ctermid(char *); +#define L_ctermid 20 +#endif + + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +#define P_tmpdir "/tmp" +char *tempnam(const char *, const char *); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define L_cuserid 20 +char *cuserid(char *); +void setlinebuf(FILE *); +void setbuffer(FILE *, char *, size_t); +int fgetc_unlocked(FILE *); +int fputc_unlocked(int, FILE *); +int fflush_unlocked(FILE *); +size_t fread_unlocked(void *, size_t, size_t, FILE *); +size_t fwrite_unlocked(const void *, size_t, size_t, FILE *); +void clearerr_unlocked(FILE *); +int feof_unlocked(FILE *); +int ferror_unlocked(FILE *); +int fileno_unlocked(FILE *); +int getw(FILE *); +int putw(int, FILE *); +char *fgetln(FILE *, size_t *); +int asprintf(char **, const char *, ...); +int vasprintf(char **, const char *, __isoc_va_list); +#endif + +#ifdef _GNU_SOURCE +char *fgets_unlocked(char *, int, FILE *); +int fputs_unlocked(const char *, FILE *); + +typedef ssize_t (cookie_read_function_t)(void *, char *, size_t); +typedef ssize_t (cookie_write_function_t)(void *, const char *, size_t); +typedef int (cookie_seek_function_t)(void *, off_t *, int); +typedef int (cookie_close_function_t)(void *); + +typedef struct _IO_cookie_io_functions_t { + cookie_read_function_t *read; + cookie_write_function_t *write; + cookie_seek_function_t *seek; + cookie_close_function_t *close; +} cookie_io_functions_t; + +FILE *fopencookie(void *, const char *, cookie_io_functions_t); +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define tmpfile64 tmpfile +#define fopen64 fopen +#define freopen64 freopen +#define fseeko64 fseeko +#define ftello64 ftello +#define fgetpos64 fgetpos +#define fsetpos64 fsetpos +#define fpos64_t fpos_t +#define off64_t off_t +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdio_ext.h b/c/common/test/includes/standard-library/stdio_ext.h new file mode 100644 index 0000000000..e3ab7fd4f9 --- /dev/null +++ b/c/common/test/includes/standard-library/stdio_ext.h @@ -0,0 +1,34 @@ +#ifndef _STDIO_EXT_H +#define _STDIO_EXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define FSETLOCKING_QUERY 0 +#define FSETLOCKING_INTERNAL 1 +#define FSETLOCKING_BYCALLER 2 + +void _flushlbf(void); +int __fsetlocking(FILE *, int); +int __fwriting(FILE *); +int __freading(FILE *); +int __freadable(FILE *); +int __fwritable(FILE *); +int __flbf(FILE *); +size_t __fbufsize(FILE *); +size_t __fpending(FILE *); +int __fpurge(FILE *); + +size_t __freadahead(FILE *); +const char *__freadptr(FILE *, size_t *); +void __freadptrinc(FILE *, size_t); +void __fseterr(FILE *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdlib.h b/c/common/test/includes/standard-library/stdlib.h new file mode 100644 index 0000000000..b54a051fe9 --- /dev/null +++ b/c/common/test/includes/standard-library/stdlib.h @@ -0,0 +1,176 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#define __NEED_size_t +#define __NEED_wchar_t + +#include + +int atoi (const char *); +long atol (const char *); +long long atoll (const char *); +double atof (const char *); + +float strtof (const char *__restrict, char **__restrict); +double strtod (const char *__restrict, char **__restrict); +long double strtold (const char *__restrict, char **__restrict); + +long strtol (const char *__restrict, char **__restrict, int); +unsigned long strtoul (const char *__restrict, char **__restrict, int); +long long strtoll (const char *__restrict, char **__restrict, int); +unsigned long long strtoull (const char *__restrict, char **__restrict, int); + +int rand (void); +void srand (unsigned); + +void *malloc (size_t); +void *calloc (size_t, size_t); +void *realloc (void *, size_t); +void free (void *); +void *aligned_alloc(size_t, size_t); + +_Noreturn void abort (void); +int atexit (void (*) (void)); +_Noreturn void exit (int); +_Noreturn void _Exit (int); +int at_quick_exit (void (*) (void)); +_Noreturn void quick_exit (int); + +char *getenv (const char *); + +int system (const char *); + +void *bsearch (const void *, const void *, size_t, size_t, int (*)(const void *, const void *)); +void qsort (void *, size_t, size_t, int (*)(const void *, const void *)); + +int abs (int); +long labs (long); +long long llabs (long long); + +typedef struct { int quot, rem; } div_t; +typedef struct { long quot, rem; } ldiv_t; +typedef struct { long long quot, rem; } lldiv_t; + +div_t div (int, int); +ldiv_t ldiv (long, long); +lldiv_t lldiv (long long, long long); + +int mblen (const char *, size_t); +int mbtowc (wchar_t *__restrict, const char *__restrict, size_t); +int wctomb (char *, wchar_t); +size_t mbstowcs (wchar_t *__restrict, const char *__restrict, size_t); +size_t wcstombs (char *__restrict, const wchar_t *__restrict, size_t); + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +size_t __ctype_get_mb_cur_max(void); +#define MB_CUR_MAX (__ctype_get_mb_cur_max()) + +#define RAND_MAX (0x7fffffff) + + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) + +#define WNOHANG 1 +#define WUNTRACED 2 + +#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) +#define WTERMSIG(s) ((s) & 0x7f) +#define WSTOPSIG(s) WEXITSTATUS(s) +#define WIFEXITED(s) (!WTERMSIG(s)) +#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) +#define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) + +int posix_memalign (void **, size_t, size_t); +int setenv (const char *, const char *, int); +int unsetenv (const char *); +int mkstemp (char *); +int mkostemp (char *, int); +char *mkdtemp (char *); +int getsubopt (char **, char *const *, char **); +int rand_r (unsigned *); + +#endif + + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +char *realpath (const char *__restrict, char *__restrict); +long int random (void); +void srandom (unsigned int); +char *initstate (unsigned int, char *, size_t); +char *setstate (char *); +int putenv (char *); +int posix_openpt (int); +int grantpt (int); +int unlockpt (int); +char *ptsname (int); +char *l64a (long); +long a64l (const char *); +void setkey (const char *); +double drand48 (void); +double erand48 (unsigned short [3]); +long int lrand48 (void); +long int nrand48 (unsigned short [3]); +long mrand48 (void); +long jrand48 (unsigned short [3]); +void srand48 (long); +unsigned short *seed48 (unsigned short [3]); +void lcong48 (unsigned short [7]); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#include +char *mktemp (char *); +int mkstemps (char *, int); +int mkostemps (char *, int, int); +void *valloc (size_t); +void *memalign(size_t, size_t); +int getloadavg(double *, int); +int clearenv(void); +#define WCOREDUMP(s) ((s) & 0x80) +#define WIFCONTINUED(s) ((s) == 0xffff) +void *reallocarray (void *, size_t, size_t); +#endif + +#ifdef _GNU_SOURCE +int ptsname_r(int, char *, size_t); +char *ecvt(double, int, int *, int *); +char *fcvt(double, int, int *, int *); +char *gcvt(double, int, char *); +char *secure_getenv(const char *); +struct __locale_struct; +float strtof_l(const char *__restrict, char **__restrict, struct __locale_struct *); +double strtod_l(const char *__restrict, char **__restrict, struct __locale_struct *); +long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *); +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define mkstemp64 mkstemp +#define mkostemp64 mkostemp +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define mkstemps64 mkstemps +#define mkostemps64 mkostemps +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stdnoreturn.h b/c/common/test/includes/standard-library/stdnoreturn.h new file mode 100644 index 0000000000..5c6aeeb008 --- /dev/null +++ b/c/common/test/includes/standard-library/stdnoreturn.h @@ -0,0 +1,7 @@ +#ifndef _STDNORETURN_H +#define _STDNORETURN_H +#ifndef __cplusplus +#include +#define noreturn _Noreturn +#endif +#endif diff --git a/c/common/test/includes/standard-library/string.h b/c/common/test/includes/standard-library/string.h new file mode 100644 index 0000000000..795a2abcd9 --- /dev/null +++ b/c/common/test/includes/standard-library/string.h @@ -0,0 +1,105 @@ +#ifndef _STRING_H +#define _STRING_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#define __NEED_size_t +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +#define __NEED_locale_t +#endif + +#include + +void *memcpy (void *__restrict, const void *__restrict, size_t); +void *memmove (void *, const void *, size_t); +void *memset (void *, int, size_t); +int memcmp (const void *, const void *, size_t); +void *memchr (const void *, int, size_t); + +char *strcpy (char *__restrict, const char *__restrict); +char *strncpy (char *__restrict, const char *__restrict, size_t); + +char *strcat (char *__restrict, const char *__restrict); +char *strncat (char *__restrict, const char *__restrict, size_t); + +int strcmp (const char *, const char *); +int strncmp (const char *, const char *, size_t); + +int strcoll (const char *, const char *); +size_t strxfrm (char *__restrict, const char *__restrict, size_t); + +char *strchr (const char *, int); +char *strrchr (const char *, int); + +size_t strcspn (const char *, const char *); +size_t strspn (const char *, const char *); +char *strpbrk (const char *, const char *); +char *strstr (const char *, const char *); +char *strtok (char *__restrict, const char *__restrict); + +size_t strlen (const char *); + +char *strerror (int); + +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#include +#endif + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +char *strtok_r (char *__restrict, const char *__restrict, char **__restrict); +int strerror_r (int, char *, size_t); +char *stpcpy(char *__restrict, const char *__restrict); +char *stpncpy(char *__restrict, const char *__restrict, size_t); +size_t strnlen (const char *, size_t); +char *strdup (const char *); +char *strndup (const char *, size_t); +char *strsignal(int); +char *strerror_l (int, locale_t); +int strcoll_l (const char *, const char *, locale_t); +size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t); +#endif + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +void *memccpy (void *__restrict, const void *__restrict, int, size_t); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +char *strsep(char **, const char *); +size_t strlcat (char *, const char *, size_t); +size_t strlcpy (char *, const char *, size_t); +void explicit_bzero (void *, size_t); +#endif + +#ifdef _GNU_SOURCE +#define strdupa(x) strcpy(alloca(strlen(x)+1),x) +int strverscmp (const char *, const char *); +char *strchrnul(const char *, int); +char *strcasestr(const char *, const char *); +void *memmem(const void *, size_t, const void *, size_t); +void *memrchr(const void *, int, size_t); +void *mempcpy(void *, const void *, size_t); +#ifndef __cplusplus +char *basename(); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/strings.h b/c/common/test/includes/standard-library/strings.h new file mode 100644 index 0000000000..db0960b4eb --- /dev/null +++ b/c/common/test/includes/standard-library/strings.h @@ -0,0 +1,39 @@ +#ifndef _STRINGS_H +#define _STRINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define __NEED_size_t +#define __NEED_locale_t +#include + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \ + || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) +int bcmp (const void *, const void *, size_t); +void bcopy (const void *, void *, size_t); +void bzero (void *, size_t); +char *index (const char *, int); +char *rindex (const char *, int); +#endif + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int ffs (int); +int ffsl (long); +int ffsll (long long); +#endif + +int strcasecmp (const char *, const char *); +int strncasecmp (const char *, const char *, size_t); + +int strcasecmp_l (const char *, const char *, locale_t); +int strncasecmp_l (const char *, const char *, size_t, locale_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/stropts.h b/c/common/test/includes/standard-library/stropts.h new file mode 100644 index 0000000000..c99c922e34 --- /dev/null +++ b/c/common/test/includes/standard-library/stropts.h @@ -0,0 +1,139 @@ +#ifndef _STROPTS_H +#define _STROPTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __SID ('S' << 8) + +#define I_NREAD (__SID | 1) +#define I_PUSH (__SID | 2) +#define I_POP (__SID | 3) +#define I_LOOK (__SID | 4) +#define I_FLUSH (__SID | 5) +#define I_SRDOPT (__SID | 6) +#define I_GRDOPT (__SID | 7) +#define I_STR (__SID | 8) +#define I_SETSIG (__SID | 9) +#define I_GETSIG (__SID |10) +#define I_FIND (__SID |11) +#define I_LINK (__SID |12) +#define I_UNLINK (__SID |13) +#define I_PEEK (__SID |15) +#define I_FDINSERT (__SID |16) +#define I_SENDFD (__SID |17) +#define I_RECVFD (__SID |14) +#define I_SWROPT (__SID |19) +#define I_GWROPT (__SID |20) +#define I_LIST (__SID |21) +#define I_PLINK (__SID |22) +#define I_PUNLINK (__SID |23) +#define I_FLUSHBAND (__SID |28) +#define I_CKBAND (__SID |29) +#define I_GETBAND (__SID |30) +#define I_ATMARK (__SID |31) +#define I_SETCLTIME (__SID |32) +#define I_GETCLTIME (__SID |33) +#define I_CANPUT (__SID |34) + +#define FMNAMESZ 8 + +#define FLUSHR 0x01 +#define FLUSHW 0x02 +#define FLUSHRW 0x03 +#define FLUSHBAND 0x04 + +#define S_INPUT 0x0001 +#define S_HIPRI 0x0002 +#define S_OUTPUT 0x0004 +#define S_MSG 0x0008 +#define S_ERROR 0x0010 +#define S_HANGUP 0x0020 +#define S_RDNORM 0x0040 +#define S_WRNORM S_OUTPUT +#define S_RDBAND 0x0080 +#define S_WRBAND 0x0100 +#define S_BANDURG 0x0200 + +#define RS_HIPRI 0x01 + +#define RNORM 0x0000 +#define RMSGD 0x0001 +#define RMSGN 0x0002 +#define RPROTDAT 0x0004 +#define RPROTDIS 0x0008 +#define RPROTNORM 0x0010 +#define RPROTMASK 0x001C + +#define SNDZERO 0x001 +#define SNDPIPE 0x002 + +#define ANYMARK 0x01 +#define LASTMARK 0x02 + +#define MUXID_ALL (-1) + +#define MSG_HIPRI 0x01 +#define MSG_ANY 0x02 +#define MSG_BAND 0x04 + +#define MORECTL 1 +#define MOREDATA 2 + +struct bandinfo { + unsigned char bi_pri; + int bi_flag; +}; + +struct strbuf { + int maxlen; + int len; + char *buf; +}; + +struct strpeek { + struct strbuf ctlbuf; + struct strbuf databuf; + unsigned flags; +}; + +struct strfdinsert { + struct strbuf ctlbuf; + struct strbuf databuf; + unsigned flags; + int fildes; + int offset; +}; + +struct strioctl { + int ic_cmd; + int ic_timout; + int ic_len; + char *ic_dp; +}; + +struct strrecvfd { + int fd; + int uid; + int gid; + char __fill[8]; +}; + +struct str_mlist { + char l_name[FMNAMESZ + 1]; +}; + +struct str_list { + int sl_nmods; + struct str_mlist *sl_modlist; +}; + +int isastream(int); +int ioctl(int, int, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/acct.h b/c/common/test/includes/standard-library/sys/acct.h new file mode 100644 index 0000000000..fae9d0508f --- /dev/null +++ b/c/common/test/includes/standard-library/sys/acct.h @@ -0,0 +1,72 @@ +#ifndef _SYS_ACCT_H +#define _SYS_ACCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define ACCT_COMM 16 + +typedef uint16_t comp_t; + +struct acct { + char ac_flag; + uint16_t ac_uid; + uint16_t ac_gid; + uint16_t ac_tty; + uint32_t ac_btime; + comp_t ac_utime; + comp_t ac_stime; + comp_t ac_etime; + comp_t ac_mem; + comp_t ac_io; + comp_t ac_rw; + comp_t ac_minflt; + comp_t ac_majflt; + comp_t ac_swaps; + uint32_t ac_exitcode; + char ac_comm[ACCT_COMM+1]; + char ac_pad[10]; +}; + + +struct acct_v3 { + char ac_flag; + char ac_version; + uint16_t ac_tty; + uint32_t ac_exitcode; + uint32_t ac_uid; + uint32_t ac_gid; + uint32_t ac_pid; + uint32_t ac_ppid; + uint32_t ac_btime; + float ac_etime; + comp_t ac_utime; + comp_t ac_stime; + comp_t ac_mem; + comp_t ac_io; + comp_t ac_rw; + comp_t ac_minflt; + comp_t ac_majflt; + comp_t ac_swaps; + char ac_comm[ACCT_COMM]; +}; + +#define AFORK 1 +#define ASU 2 +#define ACORE 8 +#define AXSIG 16 +#define ACCT_BYTEORDER (128*(__BYTE_ORDER==__BIG_ENDIAN)) +#define AHZ 100 + +int acct(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/auxv.h b/c/common/test/includes/standard-library/sys/auxv.h new file mode 100644 index 0000000000..ddccf57ff6 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/auxv.h @@ -0,0 +1,17 @@ +#ifndef _SYS_AUXV_H +#define _SYS_AUXV_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +unsigned long getauxval(unsigned long); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/cachectl.h b/c/common/test/includes/standard-library/sys/cachectl.h new file mode 100644 index 0000000000..f3b896a8e0 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/cachectl.h @@ -0,0 +1,22 @@ +#ifndef _SYS_CACHECTL_H +#define _SYS_CACHECTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ICACHE (1<<0) +#define DCACHE (1<<1) +#define BCACHE (ICACHE|DCACHE) +#define CACHEABLE 0 +#define UNCACHEABLE 1 + +int cachectl(void *, int, int); +int cacheflush(void *, int, int); +int _flush_cache(void *, int, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/dir.h b/c/common/test/includes/standard-library/sys/dir.h new file mode 100644 index 0000000000..9ba1c79e2a --- /dev/null +++ b/c/common/test/includes/standard-library/sys/dir.h @@ -0,0 +1,2 @@ +#include +#define direct dirent diff --git a/c/common/test/includes/standard-library/sys/epoll.h b/c/common/test/includes/standard-library/sys/epoll.h new file mode 100644 index 0000000000..ac81a8418a --- /dev/null +++ b/c/common/test/includes/standard-library/sys/epoll.h @@ -0,0 +1,69 @@ +#ifndef _SYS_EPOLL_H +#define _SYS_EPOLL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define __NEED_sigset_t + +#include + +#define EPOLL_CLOEXEC O_CLOEXEC +#define EPOLL_NONBLOCK O_NONBLOCK + +enum EPOLL_EVENTS { __EPOLL_DUMMY }; +#define EPOLLIN 0x001 +#define EPOLLPRI 0x002 +#define EPOLLOUT 0x004 +#define EPOLLRDNORM 0x040 +#define EPOLLNVAL 0x020 +#define EPOLLRDBAND 0x080 +#define EPOLLWRNORM 0x100 +#define EPOLLWRBAND 0x200 +#define EPOLLMSG 0x400 +#define EPOLLERR 0x008 +#define EPOLLHUP 0x010 +#define EPOLLRDHUP 0x2000 +#define EPOLLEXCLUSIVE (1U<<28) +#define EPOLLWAKEUP (1U<<29) +#define EPOLLONESHOT (1U<<30) +#define EPOLLET (1U<<31) + +#define EPOLL_CTL_ADD 1 +#define EPOLL_CTL_DEL 2 +#define EPOLL_CTL_MOD 3 + +typedef union epoll_data { + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event { + uint32_t events; + epoll_data_t data; +} +#ifdef __x86_64__ +__attribute__ ((__packed__)) +#endif +; + + +int epoll_create(int); +int epoll_create1(int); +int epoll_ctl(int, int, int, struct epoll_event *); +int epoll_wait(int, struct epoll_event *, int, int); +int epoll_pwait(int, struct epoll_event *, int, int, const sigset_t *); + + +#ifdef __cplusplus +} +#endif + +#endif /* sys/epoll.h */ diff --git a/c/common/test/includes/standard-library/sys/errno.h b/c/common/test/includes/standard-library/sys/errno.h new file mode 100644 index 0000000000..35a3e5a2a2 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/errno.h @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff --git a/c/common/test/includes/standard-library/sys/eventfd.h b/c/common/test/includes/standard-library/sys/eventfd.h new file mode 100644 index 0000000000..dc5c88f041 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/eventfd.h @@ -0,0 +1,26 @@ +#ifndef _SYS_EVENTFD_H +#define _SYS_EVENTFD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +typedef uint64_t eventfd_t; + +#define EFD_SEMAPHORE 1 +#define EFD_CLOEXEC O_CLOEXEC +#define EFD_NONBLOCK O_NONBLOCK + +int eventfd(unsigned int, int); +int eventfd_read(int, eventfd_t *); +int eventfd_write(int, eventfd_t); + + +#ifdef __cplusplus +} +#endif + +#endif /* sys/eventfd.h */ diff --git a/c/common/test/includes/standard-library/sys/fanotify.h b/c/common/test/includes/standard-library/sys/fanotify.h new file mode 100644 index 0000000000..10e5f15e24 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/fanotify.h @@ -0,0 +1,111 @@ +#ifndef _FANOTIFY_H +#define _FANOTIFY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct fanotify_event_metadata { + unsigned event_len; + unsigned char vers; + unsigned char reserved; + unsigned short metadata_len; + unsigned long long mask +#ifdef __GNUC__ + __attribute__((__aligned__(8))) +#endif + ; + int fd; + int pid; +}; + +struct fanotify_event_info_header { + unsigned char info_type; + unsigned char pad; + unsigned short len; +}; + +struct fanotify_event_info_fid { + struct fanotify_event_info_header hdr; + fsid_t fsid; + unsigned char handle[]; +}; + +struct fanotify_response { + int fd; + unsigned response; +}; + +#define FAN_ACCESS 0x01 +#define FAN_MODIFY 0x02 +#define FAN_ATTRIB 0x04 +#define FAN_CLOSE_WRITE 0x08 +#define FAN_CLOSE_NOWRITE 0x10 +#define FAN_OPEN 0x20 +#define FAN_MOVED_FROM 0x40 +#define FAN_MOVED_TO 0x80 +#define FAN_CREATE 0x100 +#define FAN_DELETE 0x200 +#define FAN_DELETE_SELF 0x400 +#define FAN_MOVE_SELF 0x800 +#define FAN_OPEN_EXEC 0x1000 +#define FAN_Q_OVERFLOW 0x4000 +#define FAN_OPEN_PERM 0x10000 +#define FAN_ACCESS_PERM 0x20000 +#define FAN_OPEN_EXEC_PERM 0x40000 +#define FAN_DIR_MODIFY 0x00080000 +#define FAN_EVENT_ON_CHILD 0x08000000 +#define FAN_ONDIR 0x40000000 +#define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE) +#define FAN_MOVE (FAN_MOVED_FROM | FAN_MOVED_TO) +#define FAN_CLOEXEC 0x01 +#define FAN_NONBLOCK 0x02 +#define FAN_CLASS_NOTIF 0 +#define FAN_CLASS_CONTENT 0x04 +#define FAN_CLASS_PRE_CONTENT 0x08 +#define FAN_ALL_CLASS_BITS (FAN_CLASS_NOTIF | FAN_CLASS_CONTENT | FAN_CLASS_PRE_CONTENT) +#define FAN_UNLIMITED_QUEUE 0x10 +#define FAN_UNLIMITED_MARKS 0x20 +#define FAN_ENABLE_AUDIT 0x40 +#define FAN_REPORT_TID 0x100 +#define FAN_REPORT_FID 0x200 +#define FAN_REPORT_DIR_FID 0x00000400 +#define FAN_REPORT_NAME 0x00000800 +#define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME) +#define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS) +#define FAN_MARK_ADD 0x01 +#define FAN_MARK_REMOVE 0x02 +#define FAN_MARK_DONT_FOLLOW 0x04 +#define FAN_MARK_ONLYDIR 0x08 +#define FAN_MARK_IGNORED_MASK 0x20 +#define FAN_MARK_IGNORED_SURV_MODIFY 0x40 +#define FAN_MARK_FLUSH 0x80 +#define FAN_MARK_INODE 0x00 +#define FAN_MARK_MOUNT 0x10 +#define FAN_MARK_FILESYSTEM 0x100 +#define FAN_MARK_TYPE_MASK (FAN_MARK_INODE | FAN_MARK_MOUNT | FAN_MARK_FILESYSTEM) +#define FAN_ALL_MARK_FLAGS (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_DONT_FOLLOW | FAN_MARK_ONLYDIR | FAN_MARK_MOUNT | FAN_MARK_IGNORED_MASK | FAN_MARK_IGNORED_SURV_MODIFY | FAN_MARK_FLUSH) +#define FAN_ALL_EVENTS (FAN_ACCESS | FAN_MODIFY | FAN_CLOSE | FAN_OPEN) +#define FAN_ALL_PERM_EVENTS (FAN_OPEN_PERM | FAN_ACCESS_PERM) +#define FAN_ALL_OUTGOING_EVENTS (FAN_ALL_EVENTS | FAN_ALL_PERM_EVENTS | FAN_Q_OVERFLOW) +#define FANOTIFY_METADATA_VERSION 3 +#define FAN_EVENT_INFO_TYPE_FID 1 +#define FAN_EVENT_INFO_TYPE_DFID_NAME 2 +#define FAN_EVENT_INFO_TYPE_DFID 3 +#define FAN_ALLOW 0x01 +#define FAN_DENY 0x02 +#define FAN_AUDIT 0x10 +#define FAN_NOFD -1 +#define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata)) +#define FAN_EVENT_NEXT(meta, len) ((len) -= (meta)->event_len, (struct fanotify_event_metadata*)(((char *)(meta)) + (meta)->event_len)) +#define FAN_EVENT_OK(meta, len) ((long)(len) >= (long)FAN_EVENT_METADATA_LEN && (long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && (long)(meta)->event_len <= (long)(len)) + +int fanotify_init(unsigned, unsigned); +int fanotify_mark(int, unsigned, unsigned long long, int, const char *); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/fcntl.h b/c/common/test/includes/standard-library/sys/fcntl.h new file mode 100644 index 0000000000..3dd928ef69 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/fcntl.h @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff --git a/c/common/test/includes/standard-library/sys/file.h b/c/common/test/includes/standard-library/sys/file.h new file mode 100644 index 0000000000..4fc83b9818 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/file.h @@ -0,0 +1,21 @@ +#ifndef _SYS_FILE_H +#define _SYS_FILE_H +#ifdef __cplusplus +extern "C" { +#endif + +#define LOCK_SH 1 +#define LOCK_EX 2 +#define LOCK_NB 4 +#define LOCK_UN 8 + +#define L_SET 0 +#define L_INCR 1 +#define L_XTND 2 + +int flock(int, int); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/fsuid.h b/c/common/test/includes/standard-library/sys/fsuid.h new file mode 100644 index 0000000000..c7a9b8faa7 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/fsuid.h @@ -0,0 +1,20 @@ +#ifndef _SYS_FSUID_H +#define _SYS_FSUID_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_uid_t +#define __NEED_gid_t + +#include + +int setfsuid(uid_t); +int setfsgid(gid_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/inotify.h b/c/common/test/includes/standard-library/sys/inotify.h new file mode 100644 index 0000000000..69b5863199 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/inotify.h @@ -0,0 +1,58 @@ +#ifndef _SYS_INOTIFY_H +#define _SYS_INOTIFY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct inotify_event { + int wd; + uint32_t mask, cookie, len; + char name[]; +}; + +#define IN_CLOEXEC O_CLOEXEC +#define IN_NONBLOCK O_NONBLOCK + +#define IN_ACCESS 0x00000001 +#define IN_MODIFY 0x00000002 +#define IN_ATTRIB 0x00000004 +#define IN_CLOSE_WRITE 0x00000008 +#define IN_CLOSE_NOWRITE 0x00000010 +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) +#define IN_OPEN 0x00000020 +#define IN_MOVED_FROM 0x00000040 +#define IN_MOVED_TO 0x00000080 +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) +#define IN_CREATE 0x00000100 +#define IN_DELETE 0x00000200 +#define IN_DELETE_SELF 0x00000400 +#define IN_MOVE_SELF 0x00000800 +#define IN_ALL_EVENTS 0x00000fff + +#define IN_UNMOUNT 0x00002000 +#define IN_Q_OVERFLOW 0x00004000 +#define IN_IGNORED 0x00008000 + +#define IN_ONLYDIR 0x01000000 +#define IN_DONT_FOLLOW 0x02000000 +#define IN_EXCL_UNLINK 0x04000000 +#define IN_MASK_CREATE 0x10000000 +#define IN_MASK_ADD 0x20000000 + +#define IN_ISDIR 0x40000000 +#define IN_ONESHOT 0x80000000 + +int inotify_init(void); +int inotify_init1(int); +int inotify_add_watch(int, const char *, uint32_t); +int inotify_rm_watch(int, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/io.h b/c/common/test/includes/standard-library/sys/io.h new file mode 100644 index 0000000000..16658cecae --- /dev/null +++ b/c/common/test/includes/standard-library/sys/io.h @@ -0,0 +1,17 @@ +#ifndef _SYS_IO_H +#define _SYS_IO_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int iopl(int); +int ioperm(unsigned long, unsigned long, int); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/ioctl.h b/c/common/test/includes/standard-library/sys/ioctl.h new file mode 100644 index 0000000000..a9a2346ee7 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/ioctl.h @@ -0,0 +1,120 @@ +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_struct_winsize + +#include +#include + +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 +#define N_6PACK 7 +#define N_MASC 8 +#define N_R3964 9 +#define N_PROFIBUS_FDL 10 +#define N_IRDA 11 +#define N_SMSBLOCK 12 +#define N_HDLC 13 +#define N_SYNC_PPP 14 +#define N_HCI 15 +#define N_GIGASET_M101 16 +#define N_SLCAN 17 +#define N_PPS 18 +#define N_V253 19 +#define N_CAIF 20 +#define N_GSM0710 21 +#define N_TI_WL 22 +#define N_TRACESINK 23 +#define N_TRACEROUTER 24 +#define N_NCI 25 +#define N_SPEAKUP 26 +#define N_NULL 27 + +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 +#define TIOCPKT_IOCTL 64 + +#define TIOCSER_TEMT 1 + +#define SIOCADDRT 0x890B +#define SIOCDELRT 0x890C +#define SIOCRTMSG 0x890D + +#define SIOCGIFNAME 0x8910 +#define SIOCSIFLINK 0x8911 +#define SIOCGIFCONF 0x8912 +#define SIOCGIFFLAGS 0x8913 +#define SIOCSIFFLAGS 0x8914 +#define SIOCGIFADDR 0x8915 +#define SIOCSIFADDR 0x8916 +#define SIOCGIFDSTADDR 0x8917 +#define SIOCSIFDSTADDR 0x8918 +#define SIOCGIFBRDADDR 0x8919 +#define SIOCSIFBRDADDR 0x891a +#define SIOCGIFNETMASK 0x891b +#define SIOCSIFNETMASK 0x891c +#define SIOCGIFMETRIC 0x891d +#define SIOCSIFMETRIC 0x891e +#define SIOCGIFMEM 0x891f +#define SIOCSIFMEM 0x8920 +#define SIOCGIFMTU 0x8921 +#define SIOCSIFMTU 0x8922 +#define SIOCSIFNAME 0x8923 +#define SIOCSIFHWADDR 0x8924 +#define SIOCGIFENCAP 0x8925 +#define SIOCSIFENCAP 0x8926 +#define SIOCGIFHWADDR 0x8927 +#define SIOCGIFSLAVE 0x8929 +#define SIOCSIFSLAVE 0x8930 +#define SIOCADDMULTI 0x8931 +#define SIOCDELMULTI 0x8932 +#define SIOCGIFINDEX 0x8933 +#define SIOGIFINDEX SIOCGIFINDEX +#define SIOCSIFPFLAGS 0x8934 +#define SIOCGIFPFLAGS 0x8935 +#define SIOCDIFADDR 0x8936 +#define SIOCSIFHWBROADCAST 0x8937 +#define SIOCGIFCOUNT 0x8938 + +#define SIOCGIFBR 0x8940 +#define SIOCSIFBR 0x8941 + +#define SIOCGIFTXQLEN 0x8942 +#define SIOCSIFTXQLEN 0x8943 + +#define SIOCDARP 0x8953 +#define SIOCGARP 0x8954 +#define SIOCSARP 0x8955 + +#define SIOCDRARP 0x8960 +#define SIOCGRARP 0x8961 +#define SIOCSRARP 0x8962 + +#define SIOCGIFMAP 0x8970 +#define SIOCSIFMAP 0x8971 + +#define SIOCADDDLCI 0x8980 +#define SIOCDELDLCI 0x8981 + +#define SIOCDEVPRIVATE 0x89F0 +#define SIOCPROTOPRIVATE 0x89E0 + +int ioctl (int, int, ...); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/ipc.h b/c/common/test/includes/standard-library/sys/ipc.h new file mode 100644 index 0000000000..9e366b7bed --- /dev/null +++ b/c/common/test/includes/standard-library/sys/ipc.h @@ -0,0 +1,42 @@ +#ifndef _SYS_IPC_H +#define _SYS_IPC_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_uid_t +#define __NEED_gid_t +#define __NEED_mode_t +#define __NEED_key_t + +#include + +#define __ipc_perm_key __key +#define __ipc_perm_seq __seq + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __key key +#define __seq seq +#endif + +#include +#include + +#define IPC_CREAT 01000 +#define IPC_EXCL 02000 +#define IPC_NOWAIT 04000 + +#define IPC_RMID 0 +#define IPC_SET 1 +#define IPC_INFO 3 + +#define IPC_PRIVATE ((key_t) 0) + +key_t ftok (const char *, int); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/kd.h b/c/common/test/includes/standard-library/sys/kd.h new file mode 100644 index 0000000000..42122b9c3a --- /dev/null +++ b/c/common/test/includes/standard-library/sys/kd.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/klog.h b/c/common/test/includes/standard-library/sys/klog.h new file mode 100644 index 0000000000..aa66684e3f --- /dev/null +++ b/c/common/test/includes/standard-library/sys/klog.h @@ -0,0 +1,14 @@ +#ifndef _SYS_KLOG_H +#define _SYS_KLOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +int klogctl (int, char *, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/membarrier.h b/c/common/test/includes/standard-library/sys/membarrier.h new file mode 100644 index 0000000000..10cb31083c --- /dev/null +++ b/c/common/test/includes/standard-library/sys/membarrier.h @@ -0,0 +1,17 @@ +#ifndef _SYS_MEMBARRIER_H +#define _SYS_MEMBARRIER_H + +#define MEMBARRIER_CMD_QUERY 0 +#define MEMBARRIER_CMD_GLOBAL 1 +#define MEMBARRIER_CMD_GLOBAL_EXPEDITED 2 +#define MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED 4 +#define MEMBARRIER_CMD_PRIVATE_EXPEDITED 8 +#define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED 16 +#define MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE 32 +#define MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE 64 + +#define MEMBARRIER_CMD_SHARED MEMBARRIER_CMD_GLOBAL + +int membarrier(int, int); + +#endif diff --git a/c/common/test/includes/standard-library/sys/mman.h b/c/common/test/includes/standard-library/sys/mman.h new file mode 100644 index 0000000000..4d603e9104 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/mman.h @@ -0,0 +1,151 @@ +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_mode_t +#define __NEED_size_t +#define __NEED_off_t + +#if defined(_GNU_SOURCE) +#define __NEED_ssize_t +#endif + +#include + +#define MAP_FAILED ((void *) -1) + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_SHARED_VALIDATE 0x03 +#define MAP_TYPE 0x0f +#define MAP_FIXED 0x10 +#define MAP_ANON 0x20 +#define MAP_ANONYMOUS MAP_ANON +#define MAP_NORESERVE 0x4000 +#define MAP_GROWSDOWN 0x0100 +#define MAP_DENYWRITE 0x0800 +#define MAP_EXECUTABLE 0x1000 +#define MAP_LOCKED 0x2000 +#define MAP_POPULATE 0x8000 +#define MAP_NONBLOCK 0x10000 +#define MAP_STACK 0x20000 +#define MAP_HUGETLB 0x40000 +#define MAP_SYNC 0x80000 +#define MAP_FIXED_NOREPLACE 0x100000 +#define MAP_FILE 0 + +#define MAP_HUGE_SHIFT 26 +#define MAP_HUGE_MASK 0x3f +#define MAP_HUGE_64KB (16 << 26) +#define MAP_HUGE_512KB (19 << 26) +#define MAP_HUGE_1MB (20 << 26) +#define MAP_HUGE_2MB (21 << 26) +#define MAP_HUGE_8MB (23 << 26) +#define MAP_HUGE_16MB (24 << 26) +#define MAP_HUGE_32MB (25 << 26) +#define MAP_HUGE_256MB (28 << 26) +#define MAP_HUGE_512MB (29 << 26) +#define MAP_HUGE_1GB (30 << 26) +#define MAP_HUGE_2GB (31 << 26) +#define MAP_HUGE_16GB (34U << 26) + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 +#define PROT_GROWSDOWN 0x01000000 +#define PROT_GROWSUP 0x02000000 + +#define MS_ASYNC 1 +#define MS_INVALIDATE 2 +#define MS_SYNC 4 + +#define MCL_CURRENT 1 +#define MCL_FUTURE 2 +#define MCL_ONFAULT 4 + +#define POSIX_MADV_NORMAL 0 +#define POSIX_MADV_RANDOM 1 +#define POSIX_MADV_SEQUENTIAL 2 +#define POSIX_MADV_WILLNEED 3 +#define POSIX_MADV_DONTNEED 4 + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define MADV_NORMAL 0 +#define MADV_RANDOM 1 +#define MADV_SEQUENTIAL 2 +#define MADV_WILLNEED 3 +#define MADV_DONTNEED 4 +#define MADV_FREE 8 +#define MADV_REMOVE 9 +#define MADV_DONTFORK 10 +#define MADV_DOFORK 11 +#define MADV_MERGEABLE 12 +#define MADV_UNMERGEABLE 13 +#define MADV_HUGEPAGE 14 +#define MADV_NOHUGEPAGE 15 +#define MADV_DONTDUMP 16 +#define MADV_DODUMP 17 +#define MADV_WIPEONFORK 18 +#define MADV_KEEPONFORK 19 +#define MADV_COLD 20 +#define MADV_PAGEOUT 21 +#define MADV_HWPOISON 100 +#define MADV_SOFT_OFFLINE 101 +#endif + +#ifdef _GNU_SOURCE +#define MREMAP_MAYMOVE 1 +#define MREMAP_FIXED 2 +#define MREMAP_DONTUNMAP 4 + +#define MLOCK_ONFAULT 0x01 + +#define MFD_CLOEXEC 0x0001U +#define MFD_ALLOW_SEALING 0x0002U +#define MFD_HUGETLB 0x0004U +#endif + +#include + +void *mmap (void *, size_t, int, int, int, off_t); +int munmap (void *, size_t); + +int mprotect (void *, size_t, int); +int msync (void *, size_t, int); + +int posix_madvise (void *, size_t, int); + +int mlock (const void *, size_t); +int munlock (const void *, size_t); +int mlockall (int); +int munlockall (void); + +#ifdef _GNU_SOURCE +void *mremap (void *, size_t, size_t, int, ...); +int remap_file_pages (void *, size_t, int, size_t, int); +int memfd_create (const char *, unsigned); +int mlock2 (const void *, size_t, unsigned); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int madvise (void *, size_t, int); +int mincore (void *, size_t, unsigned char *); +#endif + +int shm_open (const char *, int, mode_t); +int shm_unlink (const char *); + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define mmap64 mmap +#define off64_t off_t +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/mount.h b/c/common/test/includes/standard-library/sys/mount.h new file mode 100644 index 0000000000..57a89c09ec --- /dev/null +++ b/c/common/test/includes/standard-library/sys/mount.h @@ -0,0 +1,74 @@ +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define BLKROSET _IO(0x12, 93) +#define BLKROGET _IO(0x12, 94) +#define BLKRRPART _IO(0x12, 95) +#define BLKGETSIZE _IO(0x12, 96) +#define BLKFLSBUF _IO(0x12, 97) +#define BLKRASET _IO(0x12, 98) +#define BLKRAGET _IO(0x12, 99) +#define BLKFRASET _IO(0x12,100) +#define BLKFRAGET _IO(0x12,101) +#define BLKSECTSET _IO(0x12,102) +#define BLKSECTGET _IO(0x12,103) +#define BLKSSZGET _IO(0x12,104) +#define BLKBSZGET _IOR(0x12,112,size_t) +#define BLKBSZSET _IOW(0x12,113,size_t) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) + +#define MS_RDONLY 1 +#define MS_NOSUID 2 +#define MS_NODEV 4 +#define MS_NOEXEC 8 +#define MS_SYNCHRONOUS 16 +#define MS_REMOUNT 32 +#define MS_MANDLOCK 64 +#define MS_DIRSYNC 128 +#define MS_NOATIME 1024 +#define MS_NODIRATIME 2048 +#define MS_BIND 4096 +#define MS_MOVE 8192 +#define MS_REC 16384 +#define MS_SILENT 32768 +#define MS_POSIXACL (1<<16) +#define MS_UNBINDABLE (1<<17) +#define MS_PRIVATE (1<<18) +#define MS_SLAVE (1<<19) +#define MS_SHARED (1<<20) +#define MS_RELATIME (1<<21) +#define MS_KERNMOUNT (1<<22) +#define MS_I_VERSION (1<<23) +#define MS_STRICTATIME (1<<24) +#define MS_LAZYTIME (1<<25) +#define MS_NOREMOTELOCK (1<<27) +#define MS_NOSEC (1<<28) +#define MS_BORN (1<<29) +#define MS_ACTIVE (1<<30) +#define MS_NOUSER (1U<<31) + +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|MS_LAZYTIME) + +#define MS_MGC_VAL 0xc0ed0000 +#define MS_MGC_MSK 0xffff0000 + +#define MNT_FORCE 1 +#define MNT_DETACH 2 +#define MNT_EXPIRE 4 +#define UMOUNT_NOFOLLOW 8 + +int mount(const char *, const char *, const char *, unsigned long, const void *); +int umount(const char *); +int umount2(const char *, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/msg.h b/c/common/test/includes/standard-library/sys/msg.h new file mode 100644 index 0000000000..db5c62a42f --- /dev/null +++ b/c/common/test/includes/standard-library/sys/msg.h @@ -0,0 +1,53 @@ +#ifndef _SYS_MSG_H +#define _SYS_MSG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_pid_t +#define __NEED_key_t +#define __NEED_time_t +#define __NEED_size_t +#define __NEED_ssize_t + +#include + +typedef unsigned long msgqnum_t; +typedef unsigned long msglen_t; + +#include + +#define __msg_cbytes msg_cbytes + +#define MSG_NOERROR 010000 +#define MSG_EXCEPT 020000 + +#define MSG_STAT (11 | (IPC_STAT & 0x100)) +#define MSG_INFO 12 +#define MSG_STAT_ANY (13 | (IPC_STAT & 0x100)) + +struct msginfo { + int msgpool, msgmap, msgmax, msgmnb, msgmni, msgssz, msgtql; + unsigned short msgseg; +}; + +int msgctl (int, int, struct msqid_ds *); +int msgget (key_t, int); +ssize_t msgrcv (int, void *, size_t, long, int); +int msgsnd (int, const void *, size_t, int); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +struct msgbuf { + long mtype; + char mtext[1]; +}; +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/mtio.h b/c/common/test/includes/standard-library/sys/mtio.h new file mode 100644 index 0000000000..f16a529bb4 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/mtio.h @@ -0,0 +1,188 @@ +#ifndef _SYS_MTIO_H +#define _SYS_MTIO_H + +#include +#include + +struct mtop { + short mt_op; + int mt_count; +}; + +#define _IOT_mtop _IOT (_IOTS (short), 1, _IOTS (int), 1, 0, 0) +#define _IOT_mtget _IOT (_IOTS (long), 7, 0, 0, 0, 0) +#define _IOT_mtpos _IOT_SIMPLE (long) +#define _IOT_mtconfiginfo _IOT (_IOTS (long), 2, _IOTS (short), 3, _IOTS (long), 1) + + +#define MTRESET 0 +#define MTFSF 1 +#define MTBSF 2 +#define MTFSR 3 +#define MTBSR 4 +#define MTWEOF 5 +#define MTREW 6 +#define MTOFFL 7 +#define MTNOP 8 +#define MTRETEN 9 +#define MTBSFM 10 +#define MTFSFM 11 +#define MTEOM 12 +#define MTERASE 13 +#define MTRAS1 14 +#define MTRAS2 15 +#define MTRAS3 16 +#define MTSETBLK 20 +#define MTSETDENSITY 21 +#define MTSEEK 22 +#define MTTELL 23 +#define MTSETDRVBUFFER 24 +#define MTFSS 25 +#define MTBSS 26 +#define MTWSM 27 +#define MTLOCK 28 +#define MTUNLOCK 29 +#define MTLOAD 30 +#define MTUNLOAD 31 +#define MTCOMPRESSION 32 +#define MTSETPART 33 +#define MTMKPART 34 + +struct mtget { + long mt_type; + long mt_resid; + long mt_dsreg; + long mt_gstat; + long mt_erreg; + int mt_fileno; + int mt_blkno; +}; + +#define MT_ISUNKNOWN 0x01 +#define MT_ISQIC02 0x02 +#define MT_ISWT5150 0x03 +#define MT_ISARCHIVE_5945L2 0x04 +#define MT_ISCMSJ500 0x05 +#define MT_ISTDC3610 0x06 +#define MT_ISARCHIVE_VP60I 0x07 +#define MT_ISARCHIVE_2150L 0x08 +#define MT_ISARCHIVE_2060L 0x09 +#define MT_ISARCHIVESC499 0x0A +#define MT_ISQIC02_ALL_FEATURES 0x0F +#define MT_ISWT5099EEN24 0x11 +#define MT_ISTEAC_MT2ST 0x12 +#define MT_ISEVEREX_FT40A 0x32 +#define MT_ISDDS1 0x51 +#define MT_ISDDS2 0x52 +#define MT_ISSCSI1 0x71 +#define MT_ISSCSI2 0x72 +#define MT_ISFTAPE_UNKNOWN 0x800000 +#define MT_ISFTAPE_FLAG 0x800000 + +struct mt_tape_info { + long t_type; + char *t_name; +}; + +#define MT_TAPE_INFO \ +{ \ + {MT_ISUNKNOWN, "Unknown type of tape device"}, \ + {MT_ISQIC02, "Generic QIC-02 tape streamer"}, \ + {MT_ISWT5150, "Wangtek 5150, QIC-150"}, \ + {MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \ + {MT_ISCMSJ500, "CMS Jumbo 500"}, \ + {MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \ + {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \ + {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \ + {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \ + {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \ + {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \ + {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \ + {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \ + {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \ + {MT_ISSCSI1, "Generic SCSI-1 tape"}, \ + {MT_ISSCSI2, "Generic SCSI-2 tape"}, \ + {0, 0} \ +} + +struct mtpos { + long mt_blkno; +}; + +struct mtconfiginfo { + long mt_type; + long ifc_type; + unsigned short irqnr; + unsigned short dmanr; + unsigned short port; + unsigned long debug; + unsigned have_dens:1; + unsigned have_bsf:1; + unsigned have_fsr:1; + unsigned have_bsr:1; + unsigned have_eod:1; + unsigned have_seek:1; + unsigned have_tell:1; + unsigned have_ras1:1; + unsigned have_ras2:1; + unsigned have_ras3:1; + unsigned have_qfa:1; + unsigned pad1:5; + char reserved[10]; +}; + +#define MTIOCTOP _IOW('m', 1, struct mtop) +#define MTIOCGET _IOR('m', 2, struct mtget) +#define MTIOCPOS _IOR('m', 3, struct mtpos) + +#define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) +#define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) + +#define GMT_EOF(x) ((x) & 0x80000000) +#define GMT_BOT(x) ((x) & 0x40000000) +#define GMT_EOT(x) ((x) & 0x20000000) +#define GMT_SM(x) ((x) & 0x10000000) +#define GMT_EOD(x) ((x) & 0x08000000) +#define GMT_WR_PROT(x) ((x) & 0x04000000) +#define GMT_ONLINE(x) ((x) & 0x01000000) +#define GMT_D_6250(x) ((x) & 0x00800000) +#define GMT_D_1600(x) ((x) & 0x00400000) +#define GMT_D_800(x) ((x) & 0x00200000) +#define GMT_DR_OPEN(x) ((x) & 0x00040000) +#define GMT_IM_REP_EN(x) ((x) & 0x00010000) + +#define MT_ST_BLKSIZE_SHIFT 0 +#define MT_ST_BLKSIZE_MASK 0xffffff +#define MT_ST_DENSITY_SHIFT 24 +#define MT_ST_DENSITY_MASK 0xff000000 +#define MT_ST_SOFTERR_SHIFT 0 +#define MT_ST_SOFTERR_MASK 0xffff +#define MT_ST_OPTIONS 0xf0000000 +#define MT_ST_BOOLEANS 0x10000000 +#define MT_ST_SETBOOLEANS 0x30000000 +#define MT_ST_CLEARBOOLEANS 0x40000000 +#define MT_ST_WRITE_THRESHOLD 0x20000000 +#define MT_ST_DEF_BLKSIZE 0x50000000 +#define MT_ST_DEF_OPTIONS 0x60000000 +#define MT_ST_BUFFER_WRITES 0x1 +#define MT_ST_ASYNC_WRITES 0x2 +#define MT_ST_READ_AHEAD 0x4 +#define MT_ST_DEBUGGING 0x8 +#define MT_ST_TWO_FM 0x10 +#define MT_ST_FAST_MTEOM 0x20 +#define MT_ST_AUTO_LOCK 0x40 +#define MT_ST_DEF_WRITES 0x80 +#define MT_ST_CAN_BSR 0x100 +#define MT_ST_NO_BLKLIMS 0x200 +#define MT_ST_CAN_PARTITIONS 0x400 +#define MT_ST_SCSI2LOGICAL 0x800 +#define MT_ST_CLEAR_DEFAULT 0xfffff +#define MT_ST_DEF_DENSITY (MT_ST_DEF_OPTIONS | 0x100000) +#define MT_ST_DEF_COMPRESSION (MT_ST_DEF_OPTIONS | 0x200000) +#define MT_ST_DEF_DRVBUFFER (MT_ST_DEF_OPTIONS | 0x300000) +#define MT_ST_HPLOADER_OFFSET 10000 +#ifndef DEFTAPE +# define DEFTAPE "/dev/tape" +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/param.h b/c/common/test/includes/standard-library/sys/param.h new file mode 100644 index 0000000000..ce6b801980 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/param.h @@ -0,0 +1,35 @@ +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + +#define MAXSYMLINKS 20 +#define MAXHOSTNAMELEN 64 +#define MAXNAMLEN 255 +#define MAXPATHLEN 4096 +#define NBBY 8 +#define NGROUPS 32 +#define CANBSIZ 255 +#define NOFILE 256 +#define NCARGS 131072 +#define DEV_BSIZE 512 +#define NOGROUP (-1) + +#undef MIN +#undef MAX +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +#define __bitop(x,i,o) ((x)[(i)/8] o (1<<(i)%8)) +#define setbit(x,i) __bitop(x,i,|=) +#define clrbit(x,i) __bitop(x,i,&=~) +#define isset(x,i) __bitop(x,i,&) +#define isclr(x,i) !isset(x,i) + +#define howmany(n,d) (((n)+((d)-1))/(d)) +#define roundup(n,d) (howmany(n,d)*(d)) +#define powerof2(n) !(((n)-1) & (n)) + +#include +#include +#include + +#endif diff --git a/c/common/test/includes/standard-library/sys/personality.h b/c/common/test/includes/standard-library/sys/personality.h new file mode 100644 index 0000000000..411dc47563 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/personality.h @@ -0,0 +1,49 @@ +#ifndef _PERSONALITY_H +#define _PERSONALITY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define UNAME26 0x0020000 +#define ADDR_NO_RANDOMIZE 0x0040000 +#define FDPIC_FUNCPTRS 0x0080000 +#define MMAP_PAGE_ZERO 0x0100000 +#define ADDR_COMPAT_LAYOUT 0x0200000 +#define READ_IMPLIES_EXEC 0x0400000 +#define ADDR_LIMIT_32BIT 0x0800000 +#define SHORT_INODE 0x1000000 +#define WHOLE_SECONDS 0x2000000 +#define STICKY_TIMEOUTS 0x4000000 +#define ADDR_LIMIT_3GB 0x8000000 + +#define PER_LINUX 0 +#define PER_LINUX_32BIT ADDR_LIMIT_32BIT +#define PER_LINUX_FDPIC FDPIC_FUNCPTRS +#define PER_SVR4 (1 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO) +#define PER_SVR3 (2 | STICKY_TIMEOUTS | SHORT_INODE) +#define PER_SCOSVR3 (3 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE) +#define PER_OSR5 (3 | STICKY_TIMEOUTS | WHOLE_SECONDS) +#define PER_WYSEV386 (4 | STICKY_TIMEOUTS | SHORT_INODE) +#define PER_ISCR4 (5 | STICKY_TIMEOUTS) +#define PER_BSD 6 +#define PER_SUNOS (6 | STICKY_TIMEOUTS) +#define PER_XENIX (7 | STICKY_TIMEOUTS | SHORT_INODE) +#define PER_LINUX32 8 +#define PER_LINUX32_3GB (8 | ADDR_LIMIT_3GB) +#define PER_IRIX32 (9 | STICKY_TIMEOUTS) +#define PER_IRIXN32 (0xa | STICKY_TIMEOUTS) +#define PER_IRIX64 (0x0b | STICKY_TIMEOUTS) +#define PER_RISCOS 0xc +#define PER_SOLARIS (0xd | STICKY_TIMEOUTS) +#define PER_UW7 (0xe | STICKY_TIMEOUTS | MMAP_PAGE_ZERO) +#define PER_OSF4 0xf +#define PER_HPUX 0x10 +#define PER_MASK 0xff + +int personality(unsigned long); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/poll.h b/c/common/test/includes/standard-library/sys/poll.h new file mode 100644 index 0000000000..99170401d0 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/poll.h @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff --git a/c/common/test/includes/standard-library/sys/prctl.h b/c/common/test/includes/standard-library/sys/prctl.h new file mode 100644 index 0000000000..4b9fcc0508 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/prctl.h @@ -0,0 +1,170 @@ +#ifndef _SYS_PRCTL_H +#define _SYS_PRCTL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define PR_SET_PDEATHSIG 1 +#define PR_GET_PDEATHSIG 2 +#define PR_GET_DUMPABLE 3 +#define PR_SET_DUMPABLE 4 +#define PR_GET_UNALIGN 5 +#define PR_SET_UNALIGN 6 +#define PR_UNALIGN_NOPRINT 1 +#define PR_UNALIGN_SIGBUS 2 +#define PR_GET_KEEPCAPS 7 +#define PR_SET_KEEPCAPS 8 +#define PR_GET_FPEMU 9 +#define PR_SET_FPEMU 10 +#define PR_FPEMU_NOPRINT 1 +#define PR_FPEMU_SIGFPE 2 +#define PR_GET_FPEXC 11 +#define PR_SET_FPEXC 12 +#define PR_FP_EXC_SW_ENABLE 0x80 +#define PR_FP_EXC_DIV 0x010000 +#define PR_FP_EXC_OVF 0x020000 +#define PR_FP_EXC_UND 0x040000 +#define PR_FP_EXC_RES 0x080000 +#define PR_FP_EXC_INV 0x100000 +#define PR_FP_EXC_DISABLED 0 +#define PR_FP_EXC_NONRECOV 1 +#define PR_FP_EXC_ASYNC 2 +#define PR_FP_EXC_PRECISE 3 +#define PR_GET_TIMING 13 +#define PR_SET_TIMING 14 +#define PR_TIMING_STATISTICAL 0 +#define PR_TIMING_TIMESTAMP 1 +#define PR_SET_NAME 15 +#define PR_GET_NAME 16 +#define PR_GET_ENDIAN 19 +#define PR_SET_ENDIAN 20 +#define PR_ENDIAN_BIG 0 +#define PR_ENDIAN_LITTLE 1 +#define PR_ENDIAN_PPC_LITTLE 2 +#define PR_GET_SECCOMP 21 +#define PR_SET_SECCOMP 22 +#define PR_CAPBSET_READ 23 +#define PR_CAPBSET_DROP 24 +#define PR_GET_TSC 25 +#define PR_SET_TSC 26 +#define PR_TSC_ENABLE 1 +#define PR_TSC_SIGSEGV 2 +#define PR_GET_SECUREBITS 27 +#define PR_SET_SECUREBITS 28 +#define PR_SET_TIMERSLACK 29 +#define PR_GET_TIMERSLACK 30 + +#define PR_TASK_PERF_EVENTS_DISABLE 31 +#define PR_TASK_PERF_EVENTS_ENABLE 32 + +#define PR_MCE_KILL 33 +#define PR_MCE_KILL_CLEAR 0 +#define PR_MCE_KILL_SET 1 +#define PR_MCE_KILL_LATE 0 +#define PR_MCE_KILL_EARLY 1 +#define PR_MCE_KILL_DEFAULT 2 +#define PR_MCE_KILL_GET 34 + +#define PR_SET_MM 35 +#define PR_SET_MM_START_CODE 1 +#define PR_SET_MM_END_CODE 2 +#define PR_SET_MM_START_DATA 3 +#define PR_SET_MM_END_DATA 4 +#define PR_SET_MM_START_STACK 5 +#define PR_SET_MM_START_BRK 6 +#define PR_SET_MM_BRK 7 +#define PR_SET_MM_ARG_START 8 +#define PR_SET_MM_ARG_END 9 +#define PR_SET_MM_ENV_START 10 +#define PR_SET_MM_ENV_END 11 +#define PR_SET_MM_AUXV 12 +#define PR_SET_MM_EXE_FILE 13 +#define PR_SET_MM_MAP 14 +#define PR_SET_MM_MAP_SIZE 15 + +struct prctl_mm_map { + uint64_t start_code; + uint64_t end_code; + uint64_t start_data; + uint64_t end_data; + uint64_t start_brk; + uint64_t brk; + uint64_t start_stack; + uint64_t arg_start; + uint64_t arg_end; + uint64_t env_start; + uint64_t env_end; + uint64_t *auxv; + uint32_t auxv_size; + uint32_t exe_fd; +}; + +#define PR_SET_PTRACER 0x59616d61 +#define PR_SET_PTRACER_ANY (-1UL) + +#define PR_SET_CHILD_SUBREAPER 36 +#define PR_GET_CHILD_SUBREAPER 37 + +#define PR_SET_NO_NEW_PRIVS 38 +#define PR_GET_NO_NEW_PRIVS 39 + +#define PR_GET_TID_ADDRESS 40 + +#define PR_SET_THP_DISABLE 41 +#define PR_GET_THP_DISABLE 42 + +#define PR_MPX_ENABLE_MANAGEMENT 43 +#define PR_MPX_DISABLE_MANAGEMENT 44 + +#define PR_SET_FP_MODE 45 +#define PR_GET_FP_MODE 46 +#define PR_FP_MODE_FR (1 << 0) +#define PR_FP_MODE_FRE (1 << 1) + +#define PR_CAP_AMBIENT 47 +#define PR_CAP_AMBIENT_IS_SET 1 +#define PR_CAP_AMBIENT_RAISE 2 +#define PR_CAP_AMBIENT_LOWER 3 +#define PR_CAP_AMBIENT_CLEAR_ALL 4 + +#define PR_SVE_SET_VL 50 +#define PR_SVE_SET_VL_ONEXEC (1 << 18) +#define PR_SVE_GET_VL 51 +#define PR_SVE_VL_LEN_MASK 0xffff +#define PR_SVE_VL_INHERIT (1 << 17) + +#define PR_GET_SPECULATION_CTRL 52 +#define PR_SET_SPECULATION_CTRL 53 +#define PR_SPEC_STORE_BYPASS 0 +#define PR_SPEC_INDIRECT_BRANCH 1 +#define PR_SPEC_NOT_AFFECTED 0 +#define PR_SPEC_PRCTL (1UL << 0) +#define PR_SPEC_ENABLE (1UL << 1) +#define PR_SPEC_DISABLE (1UL << 2) +#define PR_SPEC_FORCE_DISABLE (1UL << 3) +#define PR_SPEC_DISABLE_NOEXEC (1UL << 4) + +#define PR_PAC_RESET_KEYS 54 +#define PR_PAC_APIAKEY (1UL << 0) +#define PR_PAC_APIBKEY (1UL << 1) +#define PR_PAC_APDAKEY (1UL << 2) +#define PR_PAC_APDBKEY (1UL << 3) +#define PR_PAC_APGAKEY (1UL << 4) + +#define PR_SET_TAGGED_ADDR_CTRL 55 +#define PR_GET_TAGGED_ADDR_CTRL 56 +#define PR_TAGGED_ADDR_ENABLE (1UL << 0) + +#define PR_SET_IO_FLUSHER 57 +#define PR_GET_IO_FLUSHER 58 + +int prctl (int, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/procfs.h b/c/common/test/includes/standard-library/sys/procfs.h new file mode 100644 index 0000000000..38e58c168b --- /dev/null +++ b/c/common/test/includes/standard-library/sys/procfs.h @@ -0,0 +1,63 @@ +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +struct elf_siginfo { + int si_signo; + int si_code; + int si_errno; +}; + +struct elf_prstatus { + struct elf_siginfo pr_info; + short int pr_cursig; + unsigned long int pr_sigpend; + unsigned long int pr_sighold; + pid_t pr_pid; + pid_t pr_ppid; + pid_t pr_pgrp; + pid_t pr_sid; + struct { + long tv_sec, tv_usec; + } pr_utime, pr_stime, pr_cutime, pr_cstime; + elf_gregset_t pr_reg; + int pr_fpvalid; +}; + +#define ELF_PRARGSZ 80 + +struct elf_prpsinfo { + char pr_state; + char pr_sname; + char pr_zomb; + char pr_nice; + unsigned long int pr_flag; +#if UINTPTR_MAX == 0xffffffff + unsigned short int pr_uid; + unsigned short int pr_gid; +#else + unsigned int pr_uid; + unsigned int pr_gid; +#endif + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + char pr_fname[16]; + char pr_psargs[ELF_PRARGSZ]; +}; + +typedef void *psaddr_t; +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; +typedef pid_t lwpid_t; +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/ptrace.h b/c/common/test/includes/standard-library/sys/ptrace.h new file mode 100644 index 0000000000..5d62a9859a --- /dev/null +++ b/c/common/test/includes/standard-library/sys/ptrace.h @@ -0,0 +1,138 @@ +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define PTRACE_TRACEME 0 +#define PT_TRACE_ME PTRACE_TRACEME + +#define PTRACE_PEEKTEXT 1 +#define PTRACE_PEEKDATA 2 +#define PTRACE_PEEKUSER 3 +#define PTRACE_POKETEXT 4 +#define PTRACE_POKEDATA 5 +#define PTRACE_POKEUSER 6 +#define PTRACE_CONT 7 +#define PTRACE_KILL 8 +#define PTRACE_SINGLESTEP 9 +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 +#define PTRACE_ATTACH 16 +#define PTRACE_DETACH 17 +#define PTRACE_GETFPXREGS 18 +#define PTRACE_SETFPXREGS 19 +#define PTRACE_SYSCALL 24 +#define PTRACE_SETOPTIONS 0x4200 +#define PTRACE_GETEVENTMSG 0x4201 +#define PTRACE_GETSIGINFO 0x4202 +#define PTRACE_SETSIGINFO 0x4203 +#define PTRACE_GETREGSET 0x4204 +#define PTRACE_SETREGSET 0x4205 +#define PTRACE_SEIZE 0x4206 +#define PTRACE_INTERRUPT 0x4207 +#define PTRACE_LISTEN 0x4208 +#define PTRACE_PEEKSIGINFO 0x4209 +#define PTRACE_GETSIGMASK 0x420a +#define PTRACE_SETSIGMASK 0x420b +#define PTRACE_SECCOMP_GET_FILTER 0x420c +#define PTRACE_SECCOMP_GET_METADATA 0x420d +#define PTRACE_GET_SYSCALL_INFO 0x420e + +#define PT_READ_I PTRACE_PEEKTEXT +#define PT_READ_D PTRACE_PEEKDATA +#define PT_READ_U PTRACE_PEEKUSER +#define PT_WRITE_I PTRACE_POKETEXT +#define PT_WRITE_D PTRACE_POKEDATA +#define PT_WRITE_U PTRACE_POKEUSER +#define PT_CONTINUE PTRACE_CONT +#define PT_KILL PTRACE_KILL +#define PT_STEP PTRACE_SINGLESTEP +#define PT_GETREGS PTRACE_GETREGS +#define PT_SETREGS PTRACE_SETREGS +#define PT_GETFPREGS PTRACE_GETFPREGS +#define PT_SETFPREGS PTRACE_SETFPREGS +#define PT_ATTACH PTRACE_ATTACH +#define PT_DETACH PTRACE_DETACH +#define PT_GETFPXREGS PTRACE_GETFPXREGS +#define PT_SETFPXREGS PTRACE_SETFPXREGS +#define PT_SYSCALL PTRACE_SYSCALL +#define PT_SETOPTIONS PTRACE_SETOPTIONS +#define PT_GETEVENTMSG PTRACE_GETEVENTMSG +#define PT_GETSIGINFO PTRACE_GETSIGINFO +#define PT_SETSIGINFO PTRACE_SETSIGINFO + +#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_O_TRACEFORK 0x00000002 +#define PTRACE_O_TRACEVFORK 0x00000004 +#define PTRACE_O_TRACECLONE 0x00000008 +#define PTRACE_O_TRACEEXEC 0x00000010 +#define PTRACE_O_TRACEVFORKDONE 0x00000020 +#define PTRACE_O_TRACEEXIT 0x00000040 +#define PTRACE_O_TRACESECCOMP 0x00000080 +#define PTRACE_O_EXITKILL 0x00100000 +#define PTRACE_O_SUSPEND_SECCOMP 0x00200000 +#define PTRACE_O_MASK 0x003000ff + +#define PTRACE_EVENT_FORK 1 +#define PTRACE_EVENT_VFORK 2 +#define PTRACE_EVENT_CLONE 3 +#define PTRACE_EVENT_EXEC 4 +#define PTRACE_EVENT_VFORK_DONE 5 +#define PTRACE_EVENT_EXIT 6 +#define PTRACE_EVENT_SECCOMP 7 +#define PTRACE_EVENT_STOP 128 + +#define PTRACE_PEEKSIGINFO_SHARED 1 + +#define PTRACE_SYSCALL_INFO_NONE 0 +#define PTRACE_SYSCALL_INFO_ENTRY 1 +#define PTRACE_SYSCALL_INFO_EXIT 2 +#define PTRACE_SYSCALL_INFO_SECCOMP 3 + +#include + +struct __ptrace_peeksiginfo_args { + uint64_t off; + uint32_t flags; + int32_t nr; +}; + +struct __ptrace_seccomp_metadata { + uint64_t filter_off; + uint64_t flags; +}; + +struct __ptrace_syscall_info { + uint8_t op; + uint8_t __pad[3]; + uint32_t arch; + uint64_t instruction_pointer; + uint64_t stack_pointer; + union { + struct { + uint64_t nr; + uint64_t args[6]; + } entry; + struct { + int64_t rval; + uint8_t is_error; + } exit; + struct { + uint64_t nr; + uint64_t args[6]; + uint32_t ret_data; + } seccomp; + }; +}; + +long ptrace(int, ...); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/quota.h b/c/common/test/includes/standard-library/sys/quota.h new file mode 100644 index 0000000000..3ed73785df --- /dev/null +++ b/c/common/test/includes/standard-library/sys/quota.h @@ -0,0 +1,102 @@ +#ifndef _SYS_QUOTA_H +#define _SYS_QUOTA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define _LINUX_QUOTA_VERSION 2 + +#define dbtob(num) ((num) << 10) +#define btodb(num) ((num) >> 10) +#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / 1024) + +#define MAX_IQ_TIME 604800 +#define MAX_DQ_TIME 604800 + +#define MAXQUOTAS 2 +#define USRQUOTA 0 +#define GRPQUOTA 1 + +#define INITQFNAMES { "user", "group", "undefined" }; + +#define QUOTAFILENAME "quota" +#define QUOTAGROUP "staff" + +#define NR_DQHASH 43 +#define NR_DQUOTS 256 + +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +#define Q_SYNC 0x800001 +#define Q_QUOTAON 0x800002 +#define Q_QUOTAOFF 0x800003 +#define Q_GETFMT 0x800004 +#define Q_GETINFO 0x800005 +#define Q_SETINFO 0x800006 +#define Q_GETQUOTA 0x800007 +#define Q_SETQUOTA 0x800008 + +#define QFMT_VFS_OLD 1 +#define QFMT_VFS_V0 2 +#define QFMT_OCFS2 3 +#define QFMT_VFS_V1 4 + +#define QIF_BLIMITS 1 +#define QIF_SPACE 2 +#define QIF_ILIMITS 4 +#define QIF_INODES 8 +#define QIF_BTIME 16 +#define QIF_ITIME 32 +#define QIF_LIMITS (QIF_BLIMITS | QIF_ILIMITS) +#define QIF_USAGE (QIF_SPACE | QIF_INODES) +#define QIF_TIMES (QIF_BTIME | QIF_ITIME) +#define QIF_ALL (QIF_LIMITS | QIF_USAGE | QIF_TIMES) + +struct dqblk { + uint64_t dqb_bhardlimit; + uint64_t dqb_bsoftlimit; + uint64_t dqb_curspace; + uint64_t dqb_ihardlimit; + uint64_t dqb_isoftlimit; + uint64_t dqb_curinodes; + uint64_t dqb_btime; + uint64_t dqb_itime; + uint32_t dqb_valid; +}; + +#define dq_bhardlimit dq_dqb.dqb_bhardlimit +#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit +#define dq_curspace dq_dqb.dqb_curspace +#define dq_valid dq_dqb.dqb_valid +#define dq_ihardlimit dq_dqb.dqb_ihardlimit +#define dq_isoftlimit dq_dqb.dqb_isoftlimit +#define dq_curinodes dq_dqb.dqb_curinodes +#define dq_btime dq_dqb.dqb_btime +#define dq_itime dq_dqb.dqb_itime + +#define dqoff(UID) ((long long)(UID) * sizeof (struct dqblk)) + +#define IIF_BGRACE 1 +#define IIF_IGRACE 2 +#define IIF_FLAGS 4 +#define IIF_ALL (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS) + +struct dqinfo { + uint64_t dqi_bgrace; + uint64_t dqi_igrace; + uint32_t dqi_flags; + uint32_t dqi_valid; +}; + +int quotactl(int, const char *, int, char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/random.h b/c/common/test/includes/standard-library/sys/random.h new file mode 100644 index 0000000000..59e40ab897 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/random.h @@ -0,0 +1,20 @@ +#ifndef _SYS_RANDOM_H +#define _SYS_RANDOM_H +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_size_t +#define __NEED_ssize_t +#include + +#define GRND_NONBLOCK 0x0001 +#define GRND_RANDOM 0x0002 +#define GRND_INSECURE 0x0004 + +ssize_t getrandom(void *, size_t, unsigned); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/reboot.h b/c/common/test/includes/standard-library/sys/reboot.h new file mode 100644 index 0000000000..9702eddba4 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/reboot.h @@ -0,0 +1,20 @@ +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H +#ifdef __cplusplus +extern "C" { +#endif + +#define RB_AUTOBOOT 0x01234567 +#define RB_HALT_SYSTEM 0xcdef0123 +#define RB_ENABLE_CAD 0x89abcdef +#define RB_DISABLE_CAD 0 +#define RB_POWER_OFF 0x4321fedc +#define RB_SW_SUSPEND 0xd000fce2 +#define RB_KEXEC 0x45584543 + +int reboot(int); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/reg.h b/c/common/test/includes/standard-library/sys/reg.h new file mode 100644 index 0000000000..b47452d003 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/reg.h @@ -0,0 +1,9 @@ +#ifndef _SYS_REG_H +#define _SYS_REG_H + +#include +#include + +#include + +#endif diff --git a/c/common/test/includes/standard-library/sys/resource.h b/c/common/test/includes/standard-library/sys/resource.h new file mode 100644 index 0000000000..3068328d09 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/resource.h @@ -0,0 +1,116 @@ +#ifndef _SYS_RESOURCE_H +#define _SYS_RESOURCE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define __NEED_id_t + +#ifdef _GNU_SOURCE +#define __NEED_pid_t +#endif + +#include +#include + +typedef unsigned long long rlim_t; + +struct rlimit { + rlim_t rlim_cur; + rlim_t rlim_max; +}; + +struct rusage { + struct timeval ru_utime; + struct timeval ru_stime; + /* linux extentions, but useful */ + long ru_maxrss; + long ru_ixrss; + long ru_idrss; + long ru_isrss; + long ru_minflt; + long ru_majflt; + long ru_nswap; + long ru_inblock; + long ru_oublock; + long ru_msgsnd; + long ru_msgrcv; + long ru_nsignals; + long ru_nvcsw; + long ru_nivcsw; + /* room for more... */ + long __reserved[16]; +}; + +int getrlimit (int, struct rlimit *); +int setrlimit (int, const struct rlimit *); +int getrusage (int, struct rusage *); + +int getpriority (int, id_t); +int setpriority (int, id_t, int); + +#ifdef _GNU_SOURCE +int prlimit(pid_t, int, const struct rlimit *, struct rlimit *); +#define prlimit64 prlimit +#endif + +#define PRIO_MIN (-20) +#define PRIO_MAX 20 + +#define PRIO_PROCESS 0 +#define PRIO_PGRP 1 +#define PRIO_USER 2 + +#define RUSAGE_SELF 0 +#define RUSAGE_CHILDREN (-1) +#define RUSAGE_THREAD 1 + +#define RLIM_INFINITY (~0ULL) +#define RLIM_SAVED_CUR RLIM_INFINITY +#define RLIM_SAVED_MAX RLIM_INFINITY + +#define RLIMIT_CPU 0 +#define RLIMIT_FSIZE 1 +#define RLIMIT_DATA 2 +#define RLIMIT_STACK 3 +#define RLIMIT_CORE 4 +#ifndef RLIMIT_RSS +#define RLIMIT_RSS 5 +#define RLIMIT_NPROC 6 +#define RLIMIT_NOFILE 7 +#define RLIMIT_MEMLOCK 8 +#define RLIMIT_AS 9 +#endif +#define RLIMIT_LOCKS 10 +#define RLIMIT_SIGPENDING 11 +#define RLIMIT_MSGQUEUE 12 +#define RLIMIT_NICE 13 +#define RLIMIT_RTPRIO 14 +#define RLIMIT_RTTIME 15 +#define RLIMIT_NLIMITS 16 + +#define RLIM_NLIMITS RLIMIT_NLIMITS + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define RLIM64_INFINITY RLIM_INFINITY +#define RLIM64_SAVED_CUR RLIM_SAVED_CUR +#define RLIM64_SAVED_MAX RLIM_SAVED_MAX +#define getrlimit64 getrlimit +#define setrlimit64 setrlimit +#define rlimit64 rlimit +#define rlim64_t rlim_t +#endif + +#if _REDIR_TIME64 +__REDIR(getrusage, __getrusage_time64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/select.h b/c/common/test/includes/standard-library/sys/select.h new file mode 100644 index 0000000000..b3bab1d57b --- /dev/null +++ b/c/common/test/includes/standard-library/sys/select.h @@ -0,0 +1,46 @@ +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#define __NEED_time_t +#define __NEED_suseconds_t +#define __NEED_struct_timeval +#define __NEED_struct_timespec +#define __NEED_sigset_t + +#include + +#define FD_SETSIZE 1024 + +typedef unsigned long fd_mask; + +typedef struct { + unsigned long fds_bits[FD_SETSIZE / 8 / sizeof(long)]; +} fd_set; + +#define FD_ZERO(s) do { int __i; unsigned long *__b=(s)->fds_bits; for(__i=sizeof (fd_set)/sizeof (long); __i; __i--) *__b++=0; } while(0) +#define FD_SET(d, s) ((s)->fds_bits[(d)/(8*sizeof(long))] |= (1UL<<((d)%(8*sizeof(long))))) +#define FD_CLR(d, s) ((s)->fds_bits[(d)/(8*sizeof(long))] &= ~(1UL<<((d)%(8*sizeof(long))))) +#define FD_ISSET(d, s) !!((s)->fds_bits[(d)/(8*sizeof(long))] & (1UL<<((d)%(8*sizeof(long))))) + +int select (int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict, struct timeval *__restrict); +int pselect (int, fd_set *__restrict, fd_set *__restrict, fd_set *__restrict, const struct timespec *__restrict, const sigset_t *__restrict); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define NFDBITS (8*(int)sizeof(long)) +#endif + +#if _REDIR_TIME64 +__REDIR(select, __select_time64); +__REDIR(pselect, __pselect_time64); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/sem.h b/c/common/test/includes/standard-library/sys/sem.h new file mode 100644 index 0000000000..a747784ede --- /dev/null +++ b/c/common/test/includes/standard-library/sys/sem.h @@ -0,0 +1,72 @@ +#ifndef _SYS_SEM_H +#define _SYS_SEM_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#define __NEED_pid_t +#define __NEED_time_t +#ifdef _GNU_SOURCE +#define __NEED_struct_timespec +#endif +#include + +#include + +#define SEM_UNDO 0x1000 +#define GETPID 11 +#define GETVAL 12 +#define GETALL 13 +#define GETNCNT 14 +#define GETZCNT 15 +#define SETVAL 16 +#define SETALL 17 + +#include + +#define _SEM_SEMUN_UNDEFINED 1 + +#define SEM_STAT (18 | (IPC_STAT & 0x100)) +#define SEM_INFO 19 +#define SEM_STAT_ANY (20 | (IPC_STAT & 0x100)) + +struct seminfo { + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +struct sembuf { + unsigned short sem_num; + short sem_op; + short sem_flg; +}; + +int semctl(int, int, int, ...); +int semget(key_t, int, int); +int semop(int, struct sembuf *, size_t); + +#ifdef _GNU_SOURCE +int semtimedop(int, struct sembuf *, size_t, const struct timespec *); +#endif + +#if _REDIR_TIME64 +#ifdef _GNU_SOURCE +__REDIR(semtimedop, __semtimedop_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/sendfile.h b/c/common/test/includes/standard-library/sys/sendfile.h new file mode 100644 index 0000000000..e7570d8e5c --- /dev/null +++ b/c/common/test/includes/standard-library/sys/sendfile.h @@ -0,0 +1,22 @@ +#ifndef _SYS_SENDFILE_H +#define _SYS_SENDFILE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +ssize_t sendfile(int, int, off_t *, size_t); + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define sendfile64 sendfile +#define off64_t off_t +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/shm.h b/c/common/test/includes/standard-library/sys/shm.h new file mode 100644 index 0000000000..fd708cab1e --- /dev/null +++ b/c/common/test/includes/standard-library/sys/shm.h @@ -0,0 +1,70 @@ +#ifndef _SYS_SHM_H +#define _SYS_SHM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_time_t +#define __NEED_size_t +#define __NEED_pid_t + +#include + +#include + +#ifdef _GNU_SOURCE +#define __used_ids used_ids +#define __swap_attempts swap_attempts +#define __swap_successes swap_successes +#endif + +#include + +#define SHM_R 0400 +#define SHM_W 0200 + +#define SHM_RDONLY 010000 +#define SHM_RND 020000 +#define SHM_REMAP 040000 +#define SHM_EXEC 0100000 + +#define SHM_LOCK 11 +#define SHM_UNLOCK 12 +#define SHM_STAT (13 | (IPC_STAT & 0x100)) +#define SHM_INFO 14 +#define SHM_STAT_ANY (15 | (IPC_STAT & 0x100)) +#define SHM_DEST 01000 +#define SHM_LOCKED 02000 +#define SHM_HUGETLB 04000 +#define SHM_NORESERVE 010000 + +#define SHM_HUGE_SHIFT 26 +#define SHM_HUGE_MASK 0x3f +#define SHM_HUGE_64KB (16 << 26) +#define SHM_HUGE_512KB (19 << 26) +#define SHM_HUGE_1MB (20 << 26) +#define SHM_HUGE_2MB (21 << 26) +#define SHM_HUGE_8MB (23 << 26) +#define SHM_HUGE_16MB (24 << 26) +#define SHM_HUGE_32MB (25 << 26) +#define SHM_HUGE_256MB (28 << 26) +#define SHM_HUGE_512MB (29 << 26) +#define SHM_HUGE_1GB (30 << 26) +#define SHM_HUGE_2GB (31 << 26) +#define SHM_HUGE_16GB (34U << 26) + +typedef unsigned long shmatt_t; + +void *shmat(int, const void *, int); +int shmctl(int, int, struct shmid_ds *); +int shmdt(const void *); +int shmget(key_t, size_t, int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/signal.h b/c/common/test/includes/standard-library/sys/signal.h new file mode 100644 index 0000000000..45bdcc648e --- /dev/null +++ b/c/common/test/includes/standard-library/sys/signal.h @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff --git a/c/common/test/includes/standard-library/sys/signalfd.h b/c/common/test/includes/standard-library/sys/signalfd.h new file mode 100644 index 0000000000..e881e2cfdd --- /dev/null +++ b/c/common/test/includes/standard-library/sys/signalfd.h @@ -0,0 +1,49 @@ +#ifndef _SYS_SIGNALFD_H +#define _SYS_SIGNALFD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define __NEED_sigset_t + +#include + +#define SFD_CLOEXEC O_CLOEXEC +#define SFD_NONBLOCK O_NONBLOCK + +int signalfd(int, const sigset_t *, int); + +struct signalfd_siginfo { + uint32_t ssi_signo; + int32_t ssi_errno; + int32_t ssi_code; + uint32_t ssi_pid; + uint32_t ssi_uid; + int32_t ssi_fd; + uint32_t ssi_tid; + uint32_t ssi_band; + uint32_t ssi_overrun; + uint32_t ssi_trapno; + int32_t ssi_status; + int32_t ssi_int; + uint64_t ssi_ptr; + uint64_t ssi_utime; + uint64_t ssi_stime; + uint64_t ssi_addr; + uint16_t ssi_addr_lsb; + uint16_t __pad2; + int32_t ssi_syscall; + uint64_t ssi_call_addr; + uint32_t ssi_arch; + uint8_t __pad[128-14*4-5*8-2*2]; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/socket.h b/c/common/test/includes/standard-library/sys/socket.h new file mode 100644 index 0000000000..38f5bb17b3 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/socket.h @@ -0,0 +1,413 @@ +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_socklen_t +#define __NEED_sa_family_t +#define __NEED_size_t +#define __NEED_ssize_t +#define __NEED_uid_t +#define __NEED_pid_t +#define __NEED_gid_t +#define __NEED_struct_iovec + +#include + +#include + +struct msghdr { + void *msg_name; + socklen_t msg_namelen; + struct iovec *msg_iov; +#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN + int __pad1; +#endif + int msg_iovlen; +#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN + int __pad1; +#endif + void *msg_control; +#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN + int __pad2; +#endif + socklen_t msg_controllen; +#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN + int __pad2; +#endif + int msg_flags; +}; + +struct cmsghdr { +#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __BIG_ENDIAN + int __pad1; +#endif + socklen_t cmsg_len; +#if __LONG_MAX > 0x7fffffff && __BYTE_ORDER == __LITTLE_ENDIAN + int __pad1; +#endif + int cmsg_level; + int cmsg_type; +}; + +#ifdef _GNU_SOURCE +struct ucred { + pid_t pid; + uid_t uid; + gid_t gid; +}; + +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; + +struct timespec; + +int sendmmsg (int, struct mmsghdr *, unsigned int, unsigned int); +int recvmmsg (int, struct mmsghdr *, unsigned int, unsigned int, struct timespec *); +#endif + +struct linger { + int l_onoff; + int l_linger; +}; + +#define SHUT_RD 0 +#define SHUT_WR 1 +#define SHUT_RDWR 2 + +#ifndef SOCK_STREAM +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#endif + +#define SOCK_RAW 3 +#define SOCK_RDM 4 +#define SOCK_SEQPACKET 5 +#define SOCK_DCCP 6 +#define SOCK_PACKET 10 + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 02000000 +#define SOCK_NONBLOCK 04000 +#endif + +#define PF_UNSPEC 0 +#define PF_LOCAL 1 +#define PF_UNIX PF_LOCAL +#define PF_FILE PF_LOCAL +#define PF_INET 2 +#define PF_AX25 3 +#define PF_IPX 4 +#define PF_APPLETALK 5 +#define PF_NETROM 6 +#define PF_BRIDGE 7 +#define PF_ATMPVC 8 +#define PF_X25 9 +#define PF_INET6 10 +#define PF_ROSE 11 +#define PF_DECnet 12 +#define PF_NETBEUI 13 +#define PF_SECURITY 14 +#define PF_KEY 15 +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK +#define PF_PACKET 17 +#define PF_ASH 18 +#define PF_ECONET 19 +#define PF_ATMSVC 20 +#define PF_RDS 21 +#define PF_SNA 22 +#define PF_IRDA 23 +#define PF_PPPOX 24 +#define PF_WANPIPE 25 +#define PF_LLC 26 +#define PF_IB 27 +#define PF_MPLS 28 +#define PF_CAN 29 +#define PF_TIPC 30 +#define PF_BLUETOOTH 31 +#define PF_IUCV 32 +#define PF_RXRPC 33 +#define PF_ISDN 34 +#define PF_PHONET 35 +#define PF_IEEE802154 36 +#define PF_CAIF 37 +#define PF_ALG 38 +#define PF_NFC 39 +#define PF_VSOCK 40 +#define PF_KCM 41 +#define PF_QIPCRTR 42 +#define PF_SMC 43 +#define PF_XDP 44 +#define PF_MAX 45 + +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX AF_LOCAL +#define AF_FILE AF_LOCAL +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_RDS PF_RDS +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_LLC PF_LLC +#define AF_IB PF_IB +#define AF_MPLS PF_MPLS +#define AF_CAN PF_CAN +#define AF_TIPC PF_TIPC +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_IUCV PF_IUCV +#define AF_RXRPC PF_RXRPC +#define AF_ISDN PF_ISDN +#define AF_PHONET PF_PHONET +#define AF_IEEE802154 PF_IEEE802154 +#define AF_CAIF PF_CAIF +#define AF_ALG PF_ALG +#define AF_NFC PF_NFC +#define AF_VSOCK PF_VSOCK +#define AF_KCM PF_KCM +#define AF_QIPCRTR PF_QIPCRTR +#define AF_SMC PF_SMC +#define AF_XDP PF_XDP +#define AF_MAX PF_MAX + +#ifndef SO_DEBUG +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +#define SO_REUSEPORT 15 +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_ACCEPTCONN 30 +#define SO_PEERSEC 31 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_PROTOCOL 38 +#define SO_DOMAIN 39 +#endif + +#ifndef SO_RCVTIMEO +#if __LONG_MAX == 0x7fffffff +#define SO_RCVTIMEO 66 +#define SO_SNDTIMEO 67 +#else +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 +#endif +#endif + +#ifndef SO_TIMESTAMP +#if __LONG_MAX == 0x7fffffff +#define SO_TIMESTAMP 63 +#define SO_TIMESTAMPNS 64 +#define SO_TIMESTAMPING 65 +#else +#define SO_TIMESTAMP 29 +#define SO_TIMESTAMPNS 35 +#define SO_TIMESTAMPING 37 +#endif +#endif + +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 +#define SO_GET_FILTER SO_ATTACH_FILTER + +#define SO_PEERNAME 28 +#define SCM_TIMESTAMP SO_TIMESTAMP +#define SO_PASSSEC 34 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS +#define SO_MARK 36 +#define SCM_TIMESTAMPING SO_TIMESTAMPING +#define SO_RXQ_OVFL 40 +#define SO_WIFI_STATUS 41 +#define SCM_WIFI_STATUS SO_WIFI_STATUS +#define SO_PEEK_OFF 42 +#define SO_NOFCS 43 +#define SO_LOCK_FILTER 44 +#define SO_SELECT_ERR_QUEUE 45 +#define SO_BUSY_POLL 46 +#define SO_MAX_PACING_RATE 47 +#define SO_BPF_EXTENSIONS 48 +#define SO_INCOMING_CPU 49 +#define SO_ATTACH_BPF 50 +#define SO_DETACH_BPF SO_DETACH_FILTER +#define SO_ATTACH_REUSEPORT_CBPF 51 +#define SO_ATTACH_REUSEPORT_EBPF 52 +#define SO_CNX_ADVICE 53 +#define SCM_TIMESTAMPING_OPT_STATS 54 +#define SO_MEMINFO 55 +#define SO_INCOMING_NAPI_ID 56 +#define SO_COOKIE 57 +#define SCM_TIMESTAMPING_PKTINFO 58 +#define SO_PEERGROUPS 59 +#define SO_ZEROCOPY 60 +#define SO_TXTIME 61 +#define SCM_TXTIME SO_TXTIME +#define SO_BINDTOIFINDEX 62 +#define SO_DETACH_REUSEPORT_BPF 68 + +#ifndef SOL_SOCKET +#define SOL_SOCKET 1 +#endif + +#define SOL_IP 0 +#define SOL_IPV6 41 +#define SOL_ICMPV6 58 + +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 +#define SOL_AAL 265 +#define SOL_IRDA 266 +#define SOL_NETBEUI 267 +#define SOL_LLC 268 +#define SOL_DCCP 269 +#define SOL_NETLINK 270 +#define SOL_TIPC 271 +#define SOL_RXRPC 272 +#define SOL_PPPOL2TP 273 +#define SOL_BLUETOOTH 274 +#define SOL_PNPIPE 275 +#define SOL_RDS 276 +#define SOL_IUCV 277 +#define SOL_CAIF 278 +#define SOL_ALG 279 +#define SOL_NFC 280 +#define SOL_KCM 281 +#define SOL_TLS 282 +#define SOL_XDP 283 + +#define SOMAXCONN 128 + +#define MSG_OOB 0x0001 +#define MSG_PEEK 0x0002 +#define MSG_DONTROUTE 0x0004 +#define MSG_CTRUNC 0x0008 +#define MSG_PROXY 0x0010 +#define MSG_TRUNC 0x0020 +#define MSG_DONTWAIT 0x0040 +#define MSG_EOR 0x0080 +#define MSG_WAITALL 0x0100 +#define MSG_FIN 0x0200 +#define MSG_SYN 0x0400 +#define MSG_CONFIRM 0x0800 +#define MSG_RST 0x1000 +#define MSG_ERRQUEUE 0x2000 +#define MSG_NOSIGNAL 0x4000 +#define MSG_MORE 0x8000 +#define MSG_WAITFORONE 0x10000 +#define MSG_BATCH 0x40000 +#define MSG_ZEROCOPY 0x4000000 +#define MSG_FASTOPEN 0x20000000 +#define MSG_CMSG_CLOEXEC 0x40000000 + +#define __CMSG_LEN(cmsg) (((cmsg)->cmsg_len + sizeof(long) - 1) & ~(long)(sizeof(long) - 1)) +#define __CMSG_NEXT(cmsg) ((unsigned char *)(cmsg) + __CMSG_LEN(cmsg)) +#define __MHDR_END(mhdr) ((unsigned char *)(mhdr)->msg_control + (mhdr)->msg_controllen) + +#define CMSG_DATA(cmsg) ((unsigned char *) (((struct cmsghdr *)(cmsg)) + 1)) +#define CMSG_NXTHDR(mhdr, cmsg) ((cmsg)->cmsg_len < sizeof (struct cmsghdr) || \ + __CMSG_LEN(cmsg) + sizeof(struct cmsghdr) >= __MHDR_END(mhdr) - (unsigned char *)(cmsg) \ + ? 0 : (struct cmsghdr *)__CMSG_NEXT(cmsg)) +#define CMSG_FIRSTHDR(mhdr) ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) 0) + +#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) +#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr))) +#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + +#define SCM_RIGHTS 0x01 +#define SCM_CREDENTIALS 0x02 + +struct sockaddr { + sa_family_t sa_family; + char sa_data[14]; +}; + +struct sockaddr_storage { + sa_family_t ss_family; + char __ss_padding[128-sizeof(long)-sizeof(sa_family_t)]; + unsigned long __ss_align; +}; + +int socket (int, int, int); +int socketpair (int, int, int, int [2]); + +int shutdown (int, int); + +int bind (int, const struct sockaddr *, socklen_t); +int connect (int, const struct sockaddr *, socklen_t); +int listen (int, int); +int accept (int, struct sockaddr *__restrict, socklen_t *__restrict); +int accept4(int, struct sockaddr *__restrict, socklen_t *__restrict, int); + +int getsockname (int, struct sockaddr *__restrict, socklen_t *__restrict); +int getpeername (int, struct sockaddr *__restrict, socklen_t *__restrict); + +ssize_t send (int, const void *, size_t, int); +ssize_t recv (int, void *, size_t, int); +ssize_t sendto (int, const void *, size_t, int, const struct sockaddr *, socklen_t); +ssize_t recvfrom (int, void *__restrict, size_t, int, struct sockaddr *__restrict, socklen_t *__restrict); +ssize_t sendmsg (int, const struct msghdr *, int); +ssize_t recvmsg (int, struct msghdr *, int); + +int getsockopt (int, int, int, void *__restrict, socklen_t *__restrict); +int setsockopt (int, int, int, const void *, socklen_t); + +int sockatmark (int); + +#if _REDIR_TIME64 +#ifdef _GNU_SOURCE +__REDIR(recvmmsg, __recvmmsg_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/soundcard.h b/c/common/test/includes/standard-library/sys/soundcard.h new file mode 100644 index 0000000000..5ca776461e --- /dev/null +++ b/c/common/test/includes/standard-library/sys/soundcard.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/stat.h b/c/common/test/includes/standard-library/sys/stat.h new file mode 100644 index 0000000000..10d446c463 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/stat.h @@ -0,0 +1,127 @@ +#ifndef _SYS_STAT_H +#define _SYS_STAT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_dev_t +#define __NEED_ino_t +#define __NEED_mode_t +#define __NEED_nlink_t +#define __NEED_uid_t +#define __NEED_gid_t +#define __NEED_off_t +#define __NEED_time_t +#define __NEED_blksize_t +#define __NEED_blkcnt_t +#define __NEED_struct_timespec + +#include + +#include + +#define st_atime st_atim.tv_sec +#define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec + +#define S_IFMT 0170000 + +#define S_IFDIR 0040000 +#define S_IFCHR 0020000 +#define S_IFBLK 0060000 +#define S_IFREG 0100000 +#define S_IFIFO 0010000 +#define S_IFLNK 0120000 +#define S_IFSOCK 0140000 + +#define S_TYPEISMQ(buf) 0 +#define S_TYPEISSEM(buf) 0 +#define S_TYPEISSHM(buf) 0 +#define S_TYPEISTMO(buf) 0 + +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) + +#ifndef S_IRUSR +#define S_ISUID 04000 +#define S_ISGID 02000 +#define S_ISVTX 01000 +#define S_IRUSR 0400 +#define S_IWUSR 0200 +#define S_IXUSR 0100 +#define S_IRWXU 0700 +#define S_IRGRP 0040 +#define S_IWGRP 0020 +#define S_IXGRP 0010 +#define S_IRWXG 0070 +#define S_IROTH 0004 +#define S_IWOTH 0002 +#define S_IXOTH 0001 +#define S_IRWXO 0007 +#endif + +#define UTIME_NOW 0x3fffffff +#define UTIME_OMIT 0x3ffffffe + +int stat(const char *__restrict, struct stat *__restrict); +int fstat(int, struct stat *); +int lstat(const char *__restrict, struct stat *__restrict); +int fstatat(int, const char *__restrict, struct stat *__restrict, int); +int chmod(const char *, mode_t); +int fchmod(int, mode_t); +int fchmodat(int, const char *, mode_t, int); +mode_t umask(mode_t); +int mkdir(const char *, mode_t); +int mkfifo(const char *, mode_t); +int mkdirat(int, const char *, mode_t); +int mkfifoat(int, const char *, mode_t); + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int mknod(const char *, mode_t, dev_t); +int mknodat(int, const char *, mode_t, dev_t); +#endif + +int futimens(int, const struct timespec [2]); +int utimensat(int, const char *, const struct timespec [2], int); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int lchmod(const char *, mode_t); +#define S_IREAD S_IRUSR +#define S_IWRITE S_IWUSR +#define S_IEXEC S_IXUSR +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define stat64 stat +#define fstat64 fstat +#define lstat64 lstat +#define fstatat64 fstatat +#define blkcnt64_t blkcnt_t +#define fsblkcnt64_t fsblkcnt_t +#define fsfilcnt64_t fsfilcnt_t +#define ino64_t ino_t +#define off64_t off_t +#endif + +#if _REDIR_TIME64 +__REDIR(stat, __stat_time64); +__REDIR(fstat, __fstat_time64); +__REDIR(lstat, __lstat_time64); +__REDIR(fstatat, __fstatat_time64); +__REDIR(futimens, __futimens_time64); +__REDIR(utimensat, __utimensat_time64); +#endif + +#ifdef __cplusplus +} +#endif +#endif + + diff --git a/c/common/test/includes/standard-library/sys/statfs.h b/c/common/test/includes/standard-library/sys/statfs.h new file mode 100644 index 0000000000..6f4c6230f7 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/statfs.h @@ -0,0 +1,32 @@ +#ifndef _SYS_STATFS_H +#define _SYS_STATFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +typedef struct __fsid_t { + int __val[2]; +} fsid_t; + +#include + +int statfs (const char *, struct statfs *); +int fstatfs (int, struct statfs *); + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define statfs64 statfs +#define fstatfs64 fstatfs +#define fsblkcnt64_t fsblkcnt_t +#define fsfilcnt64_t fsfilcnt_t +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/statvfs.h b/c/common/test/includes/standard-library/sys/statvfs.h new file mode 100644 index 0000000000..793490b6dc --- /dev/null +++ b/c/common/test/includes/standard-library/sys/statvfs.h @@ -0,0 +1,56 @@ +#ifndef _SYS_STATVFS_H +#define _SYS_STATVFS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_fsblkcnt_t +#define __NEED_fsfilcnt_t +#include + +struct statvfs { + unsigned long f_bsize, f_frsize; + fsblkcnt_t f_blocks, f_bfree, f_bavail; + fsfilcnt_t f_files, f_ffree, f_favail; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned long f_fsid; + unsigned :8*(2*sizeof(int)-sizeof(long)); +#else + unsigned :8*(2*sizeof(int)-sizeof(long)); + unsigned long f_fsid; +#endif + unsigned long f_flag, f_namemax; + int __reserved[6]; +}; + +int statvfs (const char *__restrict, struct statvfs *__restrict); +int fstatvfs (int, struct statvfs *); + +#define ST_RDONLY 1 +#define ST_NOSUID 2 +#define ST_NODEV 4 +#define ST_NOEXEC 8 +#define ST_SYNCHRONOUS 16 +#define ST_MANDLOCK 64 +#define ST_WRITE 128 +#define ST_APPEND 256 +#define ST_IMMUTABLE 512 +#define ST_NOATIME 1024 +#define ST_NODIRATIME 2048 +#define ST_RELATIME 4096 + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define statvfs64 statvfs +#define fstatvfs64 fstatvfs +#define fsblkcnt64_t fsblkcnt_t +#define fsfilcnt64_t fsfilcnt_t +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/stropts.h b/c/common/test/includes/standard-library/sys/stropts.h new file mode 100644 index 0000000000..5b5bc02f40 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/stropts.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/swap.h b/c/common/test/includes/standard-library/sys/swap.h new file mode 100644 index 0000000000..11c0f92961 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/swap.h @@ -0,0 +1,21 @@ +#ifndef _SYS_SWAP_H +#define _SYS_SWAP_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SWAP_FLAG_PREFER 0x8000 +#define SWAP_FLAG_PRIO_MASK 0x7fff +#define SWAP_FLAG_PRIO_SHIFT 0 +#define SWAP_FLAG_DISCARD 0x10000 + +int swapon (const char *, int); +int swapoff (const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/syscall.h b/c/common/test/includes/standard-library/sys/syscall.h new file mode 100644 index 0000000000..24987ddf25 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/syscall.h @@ -0,0 +1,6 @@ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include + +#endif diff --git a/c/common/test/includes/standard-library/sys/sysinfo.h b/c/common/test/includes/standard-library/sys/sysinfo.h new file mode 100644 index 0000000000..6a3931e520 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/sysinfo.h @@ -0,0 +1,36 @@ +#ifndef _SYS_SYSINFO_H +#define _SYS_SYSINFO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SI_LOAD_SHIFT 16 + +struct sysinfo { + unsigned long uptime; + unsigned long loads[3]; + unsigned long totalram; + unsigned long freeram; + unsigned long sharedram; + unsigned long bufferram; + unsigned long totalswap; + unsigned long freeswap; + unsigned short procs, pad; + unsigned long totalhigh; + unsigned long freehigh; + unsigned mem_unit; + char __reserved[256]; +}; + +int sysinfo (struct sysinfo *); +int get_nprocs_conf (void); +int get_nprocs (void); +long get_phys_pages (void); +long get_avphys_pages (void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/syslog.h b/c/common/test/includes/standard-library/sys/syslog.h new file mode 100644 index 0000000000..7761eceebb --- /dev/null +++ b/c/common/test/includes/standard-library/sys/syslog.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/sysmacros.h b/c/common/test/includes/standard-library/sys/sysmacros.h new file mode 100644 index 0000000000..07a3ef183c --- /dev/null +++ b/c/common/test/includes/standard-library/sys/sysmacros.h @@ -0,0 +1,15 @@ +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H + +#define major(x) \ + ((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) )) +#define minor(x) \ + ((unsigned)( (((x)>>12) & 0xffffff00) | ((x) & 0x000000ff) )) + +#define makedev(x,y) ( \ + (((x)&0xfffff000ULL) << 32) | \ + (((x)&0x00000fffULL) << 8) | \ + (((y)&0xffffff00ULL) << 12) | \ + (((y)&0x000000ffULL)) ) + +#endif diff --git a/c/common/test/includes/standard-library/sys/termios.h b/c/common/test/includes/standard-library/sys/termios.h new file mode 100644 index 0000000000..f5f751f043 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/termios.h @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff --git a/c/common/test/includes/standard-library/sys/time.h b/c/common/test/includes/standard-library/sys/time.h new file mode 100644 index 0000000000..cdc67ef650 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/time.h @@ -0,0 +1,76 @@ +#ifndef _SYS_TIME_H +#define _SYS_TIME_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +int gettimeofday (struct timeval *__restrict, void *__restrict); + +#define ITIMER_REAL 0 +#define ITIMER_VIRTUAL 1 +#define ITIMER_PROF 2 + +struct itimerval { + struct timeval it_interval; + struct timeval it_value; +}; + +int getitimer (int, struct itimerval *); +int setitimer (int, const struct itimerval *__restrict, struct itimerval *__restrict); +int utimes (const char *, const struct timeval [2]); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; +int futimes(int, const struct timeval [2]); +int futimesat(int, const char *, const struct timeval [2]); +int lutimes(const char *, const struct timeval [2]); +int settimeofday(const struct timeval *, const struct timezone *); +int adjtime (const struct timeval *, struct timeval *); +#define timerisset(t) ((t)->tv_sec || (t)->tv_usec) +#define timerclear(t) ((t)->tv_sec = (t)->tv_usec = 0) +#define timercmp(s,t,op) ((s)->tv_sec == (t)->tv_sec ? \ + (s)->tv_usec op (t)->tv_usec : (s)->tv_sec op (t)->tv_sec) +#define timeradd(s,t,a) (void) ( (a)->tv_sec = (s)->tv_sec + (t)->tv_sec, \ + ((a)->tv_usec = (s)->tv_usec + (t)->tv_usec) >= 1000000 && \ + ((a)->tv_usec -= 1000000, (a)->tv_sec++) ) +#define timersub(s,t,a) (void) ( (a)->tv_sec = (s)->tv_sec - (t)->tv_sec, \ + ((a)->tv_usec = (s)->tv_usec - (t)->tv_usec) < 0 && \ + ((a)->tv_usec += 1000000, (a)->tv_sec--) ) +#endif + +#if defined(_GNU_SOURCE) +#define TIMEVAL_TO_TIMESPEC(tv, ts) ( \ + (ts)->tv_sec = (tv)->tv_sec, \ + (ts)->tv_nsec = (tv)->tv_usec * 1000, \ + (void)0 ) +#define TIMESPEC_TO_TIMEVAL(tv, ts) ( \ + (tv)->tv_sec = (ts)->tv_sec, \ + (tv)->tv_usec = (ts)->tv_nsec / 1000, \ + (void)0 ) +#endif + +#if _REDIR_TIME64 +__REDIR(gettimeofday, __gettimeofday_time64); +__REDIR(getitimer, __getitimer_time64); +__REDIR(setitimer, __setitimer_time64); +__REDIR(utimes, __utimes_time64); +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +__REDIR(futimes, __futimes_time64); +__REDIR(futimesat, __futimesat_time64); +__REDIR(lutimes, __lutimes_time64); +__REDIR(settimeofday, __settimeofday_time64); +__REDIR(adjtime, __adjtime64); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/timeb.h b/c/common/test/includes/standard-library/sys/timeb.h new file mode 100644 index 0000000000..628239b7ed --- /dev/null +++ b/c/common/test/includes/standard-library/sys/timeb.h @@ -0,0 +1,28 @@ +#ifndef _SYS_TIMEB_H +#define _SYS_TIMEB_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_time_t + +#include + +struct timeb { + time_t time; + unsigned short millitm; + short timezone, dstflag; +}; + +int ftime(struct timeb *); + +#if _REDIR_TIME64 +__REDIR(ftime, __ftime64); +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/timerfd.h b/c/common/test/includes/standard-library/sys/timerfd.h new file mode 100644 index 0000000000..1b832cdd8f --- /dev/null +++ b/c/common/test/includes/standard-library/sys/timerfd.h @@ -0,0 +1,32 @@ +#ifndef _SYS_TIMERFD_H +#define _SYS_TIMERFD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define TFD_NONBLOCK O_NONBLOCK +#define TFD_CLOEXEC O_CLOEXEC + +#define TFD_TIMER_ABSTIME 1 +#define TFD_TIMER_CANCEL_ON_SET (1 << 1) + +struct itimerspec; + +int timerfd_create(int, int); +int timerfd_settime(int, int, const struct itimerspec *, struct itimerspec *); +int timerfd_gettime(int, struct itimerspec *); + +#if _REDIR_TIME64 +__REDIR(timerfd_settime, __timerfd_settime64); +__REDIR(timerfd_gettime, __timerfd_gettime64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/times.h b/c/common/test/includes/standard-library/sys/times.h new file mode 100644 index 0000000000..80a50522d7 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/times.h @@ -0,0 +1,25 @@ +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_clock_t +#include + +struct tms { + clock_t tms_utime; + clock_t tms_stime; + clock_t tms_cutime; + clock_t tms_cstime; +}; + +clock_t times (struct tms *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/c/common/test/includes/standard-library/sys/timex.h b/c/common/test/includes/standard-library/sys/timex.h new file mode 100644 index 0000000000..8b417e1be2 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/timex.h @@ -0,0 +1,103 @@ +#ifndef _SYS_TIMEX_H +#define _SYS_TIMEX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_clockid_t + +#include + +#include + +struct ntptimeval { + struct timeval time; + long maxerror, esterror; +}; + +struct timex { + unsigned modes; + long offset, freq, maxerror, esterror; + int status; + long constant, precision, tolerance; + struct timeval time; + long tick, ppsfreq, jitter; + int shift; + long stabil, jitcnt, calcnt, errcnt, stbcnt; + int tai; + int __padding[11]; +}; + +#define ADJ_OFFSET 0x0001 +#define ADJ_FREQUENCY 0x0002 +#define ADJ_MAXERROR 0x0004 +#define ADJ_ESTERROR 0x0008 +#define ADJ_STATUS 0x0010 +#define ADJ_TIMECONST 0x0020 +#define ADJ_TAI 0x0080 +#define ADJ_SETOFFSET 0x0100 +#define ADJ_MICRO 0x1000 +#define ADJ_NANO 0x2000 +#define ADJ_TICK 0x4000 +#define ADJ_OFFSET_SINGLESHOT 0x8001 +#define ADJ_OFFSET_SS_READ 0xa001 + +#define MOD_OFFSET ADJ_OFFSET +#define MOD_FREQUENCY ADJ_FREQUENCY +#define MOD_MAXERROR ADJ_MAXERROR +#define MOD_ESTERROR ADJ_ESTERROR +#define MOD_STATUS ADJ_STATUS +#define MOD_TIMECONST ADJ_TIMECONST +#define MOD_CLKB ADJ_TICK +#define MOD_CLKA ADJ_OFFSET_SINGLESHOT +#define MOD_TAI ADJ_TAI +#define MOD_MICRO ADJ_MICRO +#define MOD_NANO ADJ_NANO + +#define STA_PLL 0x0001 +#define STA_PPSFREQ 0x0002 +#define STA_PPSTIME 0x0004 +#define STA_FLL 0x0008 + +#define STA_INS 0x0010 +#define STA_DEL 0x0020 +#define STA_UNSYNC 0x0040 +#define STA_FREQHOLD 0x0080 + +#define STA_PPSSIGNAL 0x0100 +#define STA_PPSJITTER 0x0200 +#define STA_PPSWANDER 0x0400 +#define STA_PPSERROR 0x0800 + +#define STA_CLOCKERR 0x1000 +#define STA_NANO 0x2000 +#define STA_MODE 0x4000 +#define STA_CLK 0x8000 + +#define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \ + STA_PPSERROR | STA_CLOCKERR | STA_NANO | STA_MODE | STA_CLK) + +#define TIME_OK 0 +#define TIME_INS 1 +#define TIME_DEL 2 +#define TIME_OOP 3 +#define TIME_WAIT 4 +#define TIME_ERROR 5 +#define TIME_BAD TIME_ERROR + +#define MAXTC 6 + +int adjtimex(struct timex *); +int clock_adjtime(clockid_t, struct timex *); + +#if _REDIR_TIME64 +__REDIR(adjtimex, __adjtimex_time64); +__REDIR(clock_adjtime, __clock_adjtime64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/ttydefaults.h b/c/common/test/includes/standard-library/sys/ttydefaults.h new file mode 100644 index 0000000000..edb55bc4d6 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/ttydefaults.h @@ -0,0 +1,34 @@ +#ifndef _SYS_TTYDEFAULTS_H +#define _SYS_TTYDEFAULTS_H + +#define TTYDEF_IFLAG (BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY) +#define TTYDEF_OFLAG (OPOST | ONLCR | XTABS) +#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL) +#define TTYDEF_CFLAG (CREAD | CS7 | PARENB | HUPCL) +#define TTYDEF_SPEED (B9600) +#define CTRL(x) ((x)&037) +#define CEOF CTRL('d') + +#define CEOL '\0' +#define CSTATUS '\0' + +#define CERASE 0177 +#define CINTR CTRL('c') +#define CKILL CTRL('u') +#define CMIN 1 +#define CQUIT 034 +#define CSUSP CTRL('z') +#define CTIME 0 +#define CDSUSP CTRL('y') +#define CSTART CTRL('q') +#define CSTOP CTRL('s') +#define CLNEXT CTRL('v') +#define CDISCARD CTRL('o') +#define CWERASE CTRL('w') +#define CREPRINT CTRL('r') +#define CEOT CEOF +#define CBRK CEOL +#define CRPRNT CREPRINT +#define CFLUSH CDISCARD + +#endif diff --git a/c/common/test/includes/standard-library/sys/types.h b/c/common/test/includes/standard-library/sys/types.h new file mode 100644 index 0000000000..0c35541da0 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/types.h @@ -0,0 +1,85 @@ +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_ino_t +#define __NEED_dev_t +#define __NEED_uid_t +#define __NEED_gid_t +#define __NEED_mode_t +#define __NEED_nlink_t +#define __NEED_off_t +#define __NEED_pid_t +#define __NEED_size_t +#define __NEED_ssize_t +#define __NEED_time_t +#define __NEED_timer_t +#define __NEED_clockid_t + +#define __NEED_blkcnt_t +#define __NEED_fsblkcnt_t +#define __NEED_fsfilcnt_t + +#define __NEED_id_t +#define __NEED_key_t +#define __NEED_clock_t +#define __NEED_suseconds_t +#define __NEED_blksize_t + +#define __NEED_pthread_t +#define __NEED_pthread_attr_t +#define __NEED_pthread_mutexattr_t +#define __NEED_pthread_condattr_t +#define __NEED_pthread_rwlockattr_t +#define __NEED_pthread_barrierattr_t +#define __NEED_pthread_mutex_t +#define __NEED_pthread_cond_t +#define __NEED_pthread_rwlock_t +#define __NEED_pthread_barrier_t +#define __NEED_pthread_spinlock_t +#define __NEED_pthread_key_t +#define __NEED_pthread_once_t +#define __NEED_useconds_t + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_int8_t +#define __NEED_int16_t +#define __NEED_int32_t +#define __NEED_int64_t +#define __NEED_u_int64_t +#define __NEED_register_t +#endif + +#include + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned u_int32_t; +typedef char *caddr_t; +typedef unsigned char u_char; +typedef unsigned short u_short, ushort; +typedef unsigned u_int, uint; +typedef unsigned long u_long, ulong; +typedef long long quad_t; +typedef unsigned long long u_quad_t; +#include +#include +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define blkcnt64_t blkcnt_t +#define fsblkcnt64_t fsblkcnt_t +#define fsfilcnt64_t fsfilcnt_t +#define ino64_t ino_t +#define off64_t off_t +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/ucontext.h b/c/common/test/includes/standard-library/sys/ucontext.h new file mode 100644 index 0000000000..5fdbd63dbb --- /dev/null +++ b/c/common/test/includes/standard-library/sys/ucontext.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/uio.h b/c/common/test/includes/standard-library/sys/uio.h new file mode 100644 index 0000000000..00f73a2f05 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/uio.h @@ -0,0 +1,48 @@ +#ifndef _SYS_UIO_H +#define _SYS_UIO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t +#define __NEED_ssize_t +#define __NEED_struct_iovec + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_off_t +#endif + +#ifdef _GNU_SOURCE +#define __NEED_pid_t +#endif + +#include + +#define UIO_MAXIOV 1024 + +ssize_t readv (int, const struct iovec *, int); +ssize_t writev (int, const struct iovec *, int); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +ssize_t preadv (int, const struct iovec *, int, off_t); +ssize_t pwritev (int, const struct iovec *, int, off_t); +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define preadv64 preadv +#define pwritev64 pwritev +#define off64_t off_t +#endif +#endif + +#ifdef _GNU_SOURCE +ssize_t process_vm_writev(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long); +ssize_t process_vm_readv(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/un.h b/c/common/test/includes/standard-library/sys/un.h new file mode 100644 index 0000000000..1a3193ad20 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/un.h @@ -0,0 +1,31 @@ +#ifndef _SYS_UN_H +#define _SYS_UN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_sa_family_t +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_size_t +#endif + +#include + +struct sockaddr_un { + sa_family_t sun_family; + char sun_path[108]; +}; + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +size_t strlen(const char *); +#define SUN_LEN(s) (2+strlen((s)->sun_path)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/user.h b/c/common/test/includes/standard-library/sys/user.h new file mode 100644 index 0000000000..96a0340090 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/user.h @@ -0,0 +1,16 @@ +#ifndef _SYS_USER_H +#define _SYS_USER_H +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/utsname.h b/c/common/test/includes/standard-library/sys/utsname.h new file mode 100644 index 0000000000..2c80fb5a2d --- /dev/null +++ b/c/common/test/includes/standard-library/sys/utsname.h @@ -0,0 +1,29 @@ +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct utsname { + char sysname[65]; + char nodename[65]; + char release[65]; + char version[65]; + char machine[65]; +#ifdef _GNU_SOURCE + char domainname[65]; +#else + char __domainname[65]; +#endif +}; + +int uname (struct utsname *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/sys/vfs.h b/c/common/test/includes/standard-library/sys/vfs.h new file mode 100644 index 0000000000..a899db2763 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/vfs.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/vt.h b/c/common/test/includes/standard-library/sys/vt.h new file mode 100644 index 0000000000..5000de499f --- /dev/null +++ b/c/common/test/includes/standard-library/sys/vt.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sys/wait.h b/c/common/test/includes/standard-library/sys/wait.h new file mode 100644 index 0000000000..d4b1f2e185 --- /dev/null +++ b/c/common/test/includes/standard-library/sys/wait.h @@ -0,0 +1,67 @@ +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_pid_t +#define __NEED_id_t +#include + +typedef enum { + P_ALL = 0, + P_PID = 1, + P_PGID = 2, + P_PIDFD = 3 +} idtype_t; + +pid_t wait (int *); +pid_t waitpid (pid_t, int *, int ); + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +#include +int waitid (idtype_t, id_t, siginfo_t *, int); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#include +pid_t wait3 (int *, int, struct rusage *); +pid_t wait4 (pid_t, int *, int, struct rusage *); +#endif + +#define WNOHANG 1 +#define WUNTRACED 2 + +#define WSTOPPED 2 +#define WEXITED 4 +#define WCONTINUED 8 +#define WNOWAIT 0x1000000 + +#define __WNOTHREAD 0x20000000 +#define __WALL 0x40000000 +#define __WCLONE 0x80000000 + +#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) +#define WTERMSIG(s) ((s) & 0x7f) +#define WSTOPSIG(s) WEXITSTATUS(s) +#define WCOREDUMP(s) ((s) & 0x80) +#define WIFEXITED(s) (!WTERMSIG(s)) +#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00) +#define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu) +#define WIFCONTINUED(s) ((s) == 0xffff) + +#if _REDIR_TIME64 +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +__REDIR(wait3, __wait3_time64); +__REDIR(wait4, __wait4_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/sys/xattr.h b/c/common/test/includes/standard-library/sys/xattr.h new file mode 100644 index 0000000000..eeeaafc44f --- /dev/null +++ b/c/common/test/includes/standard-library/sys/xattr.h @@ -0,0 +1,32 @@ +#ifndef _SYS_XATTR_H +#define _SYS_XATTR_H +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_ssize_t +#define __NEED_size_t +#include + +#define XATTR_CREATE 1 +#define XATTR_REPLACE 2 + +ssize_t getxattr(const char *, const char *, void *, size_t); +ssize_t lgetxattr(const char *, const char *, void *, size_t); +ssize_t fgetxattr(int, const char *, void *, size_t); +ssize_t listxattr(const char *, char *, size_t); +ssize_t llistxattr(const char *, char *, size_t); +ssize_t flistxattr(int, char *, size_t); +int setxattr(const char *, const char *, const void *, size_t, int); +int lsetxattr(const char *, const char *, const void *, size_t, int); +int fsetxattr(int, const char *, const void *, size_t, int); +int removexattr(const char *, const char *); +int lremovexattr(const char *, const char *); +int fremovexattr(int, const char *); + +#define __UAPI_DEF_XATTR 0 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/syscall.h b/c/common/test/includes/standard-library/syscall.h new file mode 100644 index 0000000000..4c30578447 --- /dev/null +++ b/c/common/test/includes/standard-library/syscall.h @@ -0,0 +1 @@ +#include diff --git a/c/common/test/includes/standard-library/sysexits.h b/c/common/test/includes/standard-library/sysexits.h new file mode 100644 index 0000000000..16eeb41935 --- /dev/null +++ b/c/common/test/includes/standard-library/sysexits.h @@ -0,0 +1,21 @@ +#ifndef _SYSEXITS_H +#define _SYSEXITS_H +#define EX_OK 0 +#define EX__BASE 64 +#define EX_USAGE 64 +#define EX_DATAERR 65 +#define EX_NOINPUT 66 +#define EX_NOUSER 67 +#define EX_NOHOST 68 +#define EX_UNAVAILABLE 69 +#define EX_SOFTWARE 70 +#define EX_OSERR 71 +#define EX_OSFILE 72 +#define EX_CANTCREAT 73 +#define EX_IOERR 74 +#define EX_TEMPFAIL 75 +#define EX_PROTOCOL 76 +#define EX_NOPERM 77 +#define EX_CONFIG 78 +#define EX__MAX 78 +#endif diff --git a/c/common/test/includes/standard-library/syslog.h b/c/common/test/includes/standard-library/syslog.h new file mode 100644 index 0000000000..5b4d2964e7 --- /dev/null +++ b/c/common/test/includes/standard-library/syslog.h @@ -0,0 +1,100 @@ +#ifndef _SYSLOG_H +#define _SYSLOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#define LOG_PRIMASK 7 +#define LOG_PRI(p) ((p)&LOG_PRIMASK) +#define LOG_MAKEPRI(f, p) (((f)<<3)|(p)) + +#define LOG_MASK(p) (1<<(p)) +#define LOG_UPTO(p) ((1<<((p)+1))-1) + +#define LOG_KERN (0<<3) +#define LOG_USER (1<<3) +#define LOG_MAIL (2<<3) +#define LOG_DAEMON (3<<3) +#define LOG_AUTH (4<<3) +#define LOG_SYSLOG (5<<3) +#define LOG_LPR (6<<3) +#define LOG_NEWS (7<<3) +#define LOG_UUCP (8<<3) +#define LOG_CRON (9<<3) +#define LOG_AUTHPRIV (10<<3) +#define LOG_FTP (11<<3) + +#define LOG_LOCAL0 (16<<3) +#define LOG_LOCAL1 (17<<3) +#define LOG_LOCAL2 (18<<3) +#define LOG_LOCAL3 (19<<3) +#define LOG_LOCAL4 (20<<3) +#define LOG_LOCAL5 (21<<3) +#define LOG_LOCAL6 (22<<3) +#define LOG_LOCAL7 (23<<3) + +#define LOG_NFACILITIES 24 +#define LOG_FACMASK 0x3f8 +#define LOG_FAC(p) (((p)&LOG_FACMASK)>>3) + +#define LOG_PID 0x01 +#define LOG_CONS 0x02 +#define LOG_ODELAY 0x04 +#define LOG_NDELAY 0x08 +#define LOG_NOWAIT 0x10 +#define LOG_PERROR 0x20 + +void closelog (void); +void openlog (const char *, int, int); +int setlogmask (int); +void syslog (int, const char *, ...); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define _PATH_LOG "/dev/log" +#define __NEED_va_list +#include +void vsyslog (int, const char *, va_list); +#if defined(SYSLOG_NAMES) +#define INTERNAL_NOPRI 0x10 +#define INTERNAL_MARK (LOG_NFACILITIES<<3) +typedef struct { + char *c_name; + int c_val; +} CODE; +#define prioritynames ((CODE *)(const CODE []){ \ + { "alert", LOG_ALERT }, { "crit", LOG_CRIT }, { "debug", LOG_DEBUG }, \ + { "emerg", LOG_EMERG }, { "err", LOG_ERR }, { "error", LOG_ERR }, \ + { "info", LOG_INFO }, { "none", INTERNAL_NOPRI }, \ + { "notice", LOG_NOTICE }, { "panic", LOG_EMERG }, \ + { "warn", LOG_WARNING }, { "warning", LOG_WARNING }, { 0, -1 } }) +#define facilitynames ((CODE *)(const CODE []){ \ + { "auth", LOG_AUTH }, { "authpriv", LOG_AUTHPRIV }, \ + { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, { "ftp", LOG_FTP }, \ + { "kern", LOG_KERN }, { "lpr", LOG_LPR }, { "mail", LOG_MAIL }, \ + { "mark", INTERNAL_MARK }, { "news", LOG_NEWS }, \ + { "security", LOG_AUTH }, { "syslog", LOG_SYSLOG }, \ + { "user", LOG_USER }, { "uucp", LOG_UUCP }, \ + { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, \ + { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, \ + { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, \ + { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { 0, -1 } }) +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/tar.h b/c/common/test/includes/standard-library/tar.h new file mode 100644 index 0000000000..be589842a8 --- /dev/null +++ b/c/common/test/includes/standard-library/tar.h @@ -0,0 +1,33 @@ +#ifndef _TAR_H +#define _TAR_H + +#define TSUID 04000 +#define TSGID 02000 +#define TSVTX 01000 +#define TUREAD 00400 +#define TUWRITE 00200 +#define TUEXEC 00100 +#define TGREAD 00040 +#define TGWRITE 00020 +#define TGEXEC 00010 +#define TOREAD 00004 +#define TOWRITE 00002 +#define TOEXEC 00001 + +#define REGTYPE '0' +#define AREGTYPE '\0' +#define LNKTYPE '1' +#define SYMTYPE '2' +#define CHRTYPE '3' +#define BLKTYPE '4' +#define DIRTYPE '5' +#define FIFOTYPE '6' +#define CONTTYPE '7' + +#define TMAGIC "ustar" +#define TMAGLEN 6 + +#define TVERSION "00" +#define TVERSLEN 2 + +#endif diff --git a/c/common/test/includes/standard-library/termios.h b/c/common/test/includes/standard-library/termios.h new file mode 100644 index 0000000000..cbb533010e --- /dev/null +++ b/c/common/test/includes/standard-library/termios.h @@ -0,0 +1,50 @@ +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_pid_t +#define __NEED_struct_winsize + +#include + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 + +#include + +speed_t cfgetospeed (const struct termios *); +speed_t cfgetispeed (const struct termios *); +int cfsetospeed (struct termios *, speed_t); +int cfsetispeed (struct termios *, speed_t); + +int tcgetattr (int, struct termios *); +int tcsetattr (int, int, const struct termios *); + +int tcgetwinsize (int, struct winsize *); +int tcsetwinsize (int, const struct winsize *); + +int tcsendbreak (int, int); +int tcdrain (int); +int tcflush (int, int); +int tcflow (int, int); + +pid_t tcgetsid (int); + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +void cfmakeraw(struct termios *); +int cfsetspeed(struct termios *, speed_t); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/tgmath.h b/c/common/test/includes/standard-library/tgmath.h new file mode 100644 index 0000000000..e41ccac9ec --- /dev/null +++ b/c/common/test/includes/standard-library/tgmath.h @@ -0,0 +1,270 @@ +#ifndef _TGMATH_H +#define _TGMATH_H + +/* +the return types are only correct with gcc (__GNUC__) +otherwise they are long double or long double complex + +the long double version of a function is never chosen when +sizeof(double) == sizeof(long double) +(but the return type is set correctly with gcc) +*/ + +#include +#include + +#define __IS_FP(x) (sizeof((x)+1ULL) == sizeof((x)+1.0f)) +#define __IS_CX(x) (__IS_FP(x) && sizeof(x) == sizeof((x)+I)) +#define __IS_REAL(x) (__IS_FP(x) && 2*sizeof(x) == sizeof((x)+I)) + +#define __FLT(x) (__IS_REAL(x) && sizeof(x) == sizeof(float)) +#define __LDBL(x) (__IS_REAL(x) && sizeof(x) == sizeof(long double) && sizeof(long double) != sizeof(double)) + +#define __FLTCX(x) (__IS_CX(x) && sizeof(x) == sizeof(float complex)) +#define __DBLCX(x) (__IS_CX(x) && sizeof(x) == sizeof(double complex)) +#define __LDBLCX(x) (__IS_CX(x) && sizeof(x) == sizeof(long double complex) && sizeof(long double) != sizeof(double)) + +/* return type */ + +#ifdef __GNUC__ +/* +the result must be casted to the right type +(otherwise the result type is determined by the conversion +rules applied to all the function return types so it is long +double or long double complex except for integral functions) + +this cannot be done in c99, so the typeof gcc extension is +used and that the type of ?: depends on wether an operand is +a null pointer constant or not +(in c11 _Generic can be used) + +the c arguments below must be integer constant expressions +so they can be in null pointer constants +(__IS_FP above was carefully chosen this way) +*/ +/* if c then t else void */ +#define __type1(c,t) __typeof__(*(0?(t*)0:(void*)!(c))) +/* if c then t1 else t2 */ +#define __type2(c,t1,t2) __typeof__(*(0?(__type1(c,t1)*)0:(__type1(!(c),t2)*)0)) +/* cast to double when x is integral, otherwise use typeof(x) */ +#define __RETCAST(x) ( \ + __type2(__IS_FP(x), __typeof__(x), double)) +/* 2 args case, should work for complex types (cpow) */ +#define __RETCAST_2(x, y) ( \ + __type2(__IS_FP(x) && __IS_FP(y), \ + __typeof__((x)+(y)), \ + __typeof__((x)+(y)+1.0))) +/* 3 args case (fma only) */ +#define __RETCAST_3(x, y, z) ( \ + __type2(__IS_FP(x) && __IS_FP(y) && __IS_FP(z), \ + __typeof__((x)+(y)+(z)), \ + __typeof__((x)+(y)+(z)+1.0))) +/* drop complex from the type of x */ +/* TODO: wrong when sizeof(long double)==sizeof(double) */ +#define __RETCAST_REAL(x) ( \ + __type2(__IS_FP(x) && sizeof((x)+I) == sizeof(float complex), float, \ + __type2(sizeof((x)+1.0+I) == sizeof(double complex), double, \ + long double))) +/* add complex to the type of x */ +#define __RETCAST_CX(x) (__typeof__(__RETCAST(x)0+I)) +#else +#define __RETCAST(x) +#define __RETCAST_2(x, y) +#define __RETCAST_3(x, y, z) +#define __RETCAST_REAL(x) +#define __RETCAST_CX(x) +#endif + +/* function selection */ + +#define __tg_real_nocast(fun, x) ( \ + __FLT(x) ? fun ## f (x) : \ + __LDBL(x) ? fun ## l (x) : \ + fun(x) ) + +#define __tg_real(fun, x) (__RETCAST(x)__tg_real_nocast(fun, x)) + +#define __tg_real_2_1(fun, x, y) (__RETCAST(x)( \ + __FLT(x) ? fun ## f (x, y) : \ + __LDBL(x) ? fun ## l (x, y) : \ + fun(x, y) )) + +#define __tg_real_2(fun, x, y) (__RETCAST_2(x, y)( \ + __FLT(x) && __FLT(y) ? fun ## f (x, y) : \ + __LDBL((x)+(y)) ? fun ## l (x, y) : \ + fun(x, y) )) + +#define __tg_complex(fun, x) (__RETCAST_CX(x)( \ + __FLTCX((x)+I) && __IS_FP(x) ? fun ## f (x) : \ + __LDBLCX((x)+I) ? fun ## l (x) : \ + fun(x) )) + +#define __tg_complex_retreal(fun, x) (__RETCAST_REAL(x)( \ + __FLTCX((x)+I) && __IS_FP(x) ? fun ## f (x) : \ + __LDBLCX((x)+I) ? fun ## l (x) : \ + fun(x) )) + +#define __tg_real_complex(fun, x) (__RETCAST(x)( \ + __FLTCX(x) ? c ## fun ## f (x) : \ + __DBLCX(x) ? c ## fun (x) : \ + __LDBLCX(x) ? c ## fun ## l (x) : \ + __FLT(x) ? fun ## f (x) : \ + __LDBL(x) ? fun ## l (x) : \ + fun(x) )) + +/* special cases */ + +#define __tg_real_remquo(x, y, z) (__RETCAST_2(x, y)( \ + __FLT(x) && __FLT(y) ? remquof(x, y, z) : \ + __LDBL((x)+(y)) ? remquol(x, y, z) : \ + remquo(x, y, z) )) + +#define __tg_real_fma(x, y, z) (__RETCAST_3(x, y, z)( \ + __FLT(x) && __FLT(y) && __FLT(z) ? fmaf(x, y, z) : \ + __LDBL((x)+(y)+(z)) ? fmal(x, y, z) : \ + fma(x, y, z) )) + +#define __tg_real_complex_pow(x, y) (__RETCAST_2(x, y)( \ + __FLTCX((x)+(y)) && __IS_FP(x) && __IS_FP(y) ? cpowf(x, y) : \ + __FLTCX((x)+(y)) ? cpow(x, y) : \ + __DBLCX((x)+(y)) ? cpow(x, y) : \ + __LDBLCX((x)+(y)) ? cpowl(x, y) : \ + __FLT(x) && __FLT(y) ? powf(x, y) : \ + __LDBL((x)+(y)) ? powl(x, y) : \ + pow(x, y) )) + +#define __tg_real_complex_fabs(x) (__RETCAST_REAL(x)( \ + __FLTCX(x) ? cabsf(x) : \ + __DBLCX(x) ? cabs(x) : \ + __LDBLCX(x) ? cabsl(x) : \ + __FLT(x) ? fabsf(x) : \ + __LDBL(x) ? fabsl(x) : \ + fabs(x) )) + +/* suppress any macros in math.h or complex.h */ + +#undef acos +#undef acosh +#undef asin +#undef asinh +#undef atan +#undef atan2 +#undef atanh +#undef carg +#undef cbrt +#undef ceil +#undef cimag +#undef conj +#undef copysign +#undef cos +#undef cosh +#undef cproj +#undef creal +#undef erf +#undef erfc +#undef exp +#undef exp2 +#undef expm1 +#undef fabs +#undef fdim +#undef floor +#undef fma +#undef fmax +#undef fmin +#undef fmod +#undef frexp +#undef hypot +#undef ilogb +#undef ldexp +#undef lgamma +#undef llrint +#undef llround +#undef log +#undef log10 +#undef log1p +#undef log2 +#undef logb +#undef lrint +#undef lround +#undef nearbyint +#undef nextafter +#undef nexttoward +#undef pow +#undef remainder +#undef remquo +#undef rint +#undef round +#undef scalbln +#undef scalbn +#undef sin +#undef sinh +#undef sqrt +#undef tan +#undef tanh +#undef tgamma +#undef trunc + +/* tg functions */ + +#define acos(x) __tg_real_complex(acos, (x)) +#define acosh(x) __tg_real_complex(acosh, (x)) +#define asin(x) __tg_real_complex(asin, (x)) +#define asinh(x) __tg_real_complex(asinh, (x)) +#define atan(x) __tg_real_complex(atan, (x)) +#define atan2(x,y) __tg_real_2(atan2, (x), (y)) +#define atanh(x) __tg_real_complex(atanh, (x)) +#define carg(x) __tg_complex_retreal(carg, (x)) +#define cbrt(x) __tg_real(cbrt, (x)) +#define ceil(x) __tg_real(ceil, (x)) +#define cimag(x) __tg_complex_retreal(cimag, (x)) +#define conj(x) __tg_complex(conj, (x)) +#define copysign(x,y) __tg_real_2(copysign, (x), (y)) +#define cos(x) __tg_real_complex(cos, (x)) +#define cosh(x) __tg_real_complex(cosh, (x)) +#define cproj(x) __tg_complex(cproj, (x)) +#define creal(x) __tg_complex_retreal(creal, (x)) +#define erf(x) __tg_real(erf, (x)) +#define erfc(x) __tg_real(erfc, (x)) +#define exp(x) __tg_real_complex(exp, (x)) +#define exp2(x) __tg_real(exp2, (x)) +#define expm1(x) __tg_real(expm1, (x)) +#define fabs(x) __tg_real_complex_fabs(x) +#define fdim(x,y) __tg_real_2(fdim, (x), (y)) +#define floor(x) __tg_real(floor, (x)) +#define fma(x,y,z) __tg_real_fma((x), (y), (z)) +#define fmax(x,y) __tg_real_2(fmax, (x), (y)) +#define fmin(x,y) __tg_real_2(fmin, (x), (y)) +#define fmod(x,y) __tg_real_2(fmod, (x), (y)) +#define frexp(x,y) __tg_real_2_1(frexp, (x), (y)) +#define hypot(x,y) __tg_real_2(hypot, (x), (y)) +#define ilogb(x) __tg_real_nocast(ilogb, (x)) +#define ldexp(x,y) __tg_real_2_1(ldexp, (x), (y)) +#define lgamma(x) __tg_real(lgamma, (x)) +#define llrint(x) __tg_real_nocast(llrint, (x)) +#define llround(x) __tg_real_nocast(llround, (x)) +#define log(x) __tg_real_complex(log, (x)) +#define log10(x) __tg_real(log10, (x)) +#define log1p(x) __tg_real(log1p, (x)) +#define log2(x) __tg_real(log2, (x)) +#define logb(x) __tg_real(logb, (x)) +#define lrint(x) __tg_real_nocast(lrint, (x)) +#define lround(x) __tg_real_nocast(lround, (x)) +#define nearbyint(x) __tg_real(nearbyint, (x)) +#define nextafter(x,y) __tg_real_2(nextafter, (x), (y)) +#define nexttoward(x,y) __tg_real_2(nexttoward, (x), (y)) +#define pow(x,y) __tg_real_complex_pow((x), (y)) +#define remainder(x,y) __tg_real_2(remainder, (x), (y)) +#define remquo(x,y,z) __tg_real_remquo((x), (y), (z)) +#define rint(x) __tg_real(rint, (x)) +#define round(x) __tg_real(round, (x)) +#define scalbln(x,y) __tg_real_2_1(scalbln, (x), (y)) +#define scalbn(x,y) __tg_real_2_1(scalbn, (x), (y)) +#define sin(x) __tg_real_complex(sin, (x)) +#define sinh(x) __tg_real_complex(sinh, (x)) +#define sqrt(x) __tg_real_complex(sqrt, (x)) +#define tan(x) __tg_real_complex(tan, (x)) +#define tanh(x) __tg_real_complex(tanh, (x)) +#define tgamma(x) __tg_real(tgamma, (x)) +#define trunc(x) __tg_real(trunc, (x)) + +#endif diff --git a/c/common/test/includes/standard-library/threads.h b/c/common/test/includes/standard-library/threads.h new file mode 100644 index 0000000000..52ec3100eb --- /dev/null +++ b/c/common/test/includes/standard-library/threads.h @@ -0,0 +1,93 @@ +#ifndef _THREADS_H +#define _THREADS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +typedef unsigned long thrd_t; +#else +typedef struct __pthread *thrd_t; +#define thread_local _Thread_local +#endif + +typedef int once_flag; +typedef unsigned tss_t; +typedef int (*thrd_start_t)(void *); +typedef void (*tss_dtor_t)(void *); + +#define __NEED_cnd_t +#define __NEED_mtx_t + +#include + +#define TSS_DTOR_ITERATIONS 4 + +enum { + thrd_success = 0, + thrd_busy = 1, + thrd_error = 2, + thrd_nomem = 3, + thrd_timedout = 4, +}; + +enum { + mtx_plain = 0, + mtx_recursive = 1, + mtx_timed = 2, +}; + +#define ONCE_FLAG_INIT 0 + +int thrd_create(thrd_t *, thrd_start_t, void *); +_Noreturn void thrd_exit(int); + +int thrd_detach(thrd_t); +int thrd_join(thrd_t, int *); + +int thrd_sleep(const struct timespec *, struct timespec *); +void thrd_yield(void); + +thrd_t thrd_current(void); +int thrd_equal(thrd_t, thrd_t); +#ifndef __cplusplus +#define thrd_equal(A, B) ((A) == (B)) +#endif + +void call_once(once_flag *, void (*)(void)); + +int mtx_init(mtx_t *, int); +void mtx_destroy(mtx_t *); + +int mtx_lock(mtx_t *); +int mtx_timedlock(mtx_t *__restrict, const struct timespec *__restrict); +int mtx_trylock(mtx_t *); +int mtx_unlock(mtx_t *); + +int cnd_init(cnd_t *); +void cnd_destroy(cnd_t *); + +int cnd_broadcast(cnd_t *); +int cnd_signal(cnd_t *); + +int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict, const struct timespec *__restrict); +int cnd_wait(cnd_t *, mtx_t *); + +int tss_create(tss_t *, tss_dtor_t); +void tss_delete(tss_t); + +int tss_set(tss_t, void *); +void *tss_get(tss_t); + +#if _REDIR_TIME64 +__REDIR(thrd_sleep, __thrd_sleep_time64); +__REDIR(mtx_timedlock, __mtx_timedlock_time64); +__REDIR(cnd_timedwait, __cnd_timedwait_time64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/time.h b/c/common/test/includes/standard-library/time.h new file mode 100644 index 0000000000..5494df1836 --- /dev/null +++ b/c/common/test/includes/standard-library/time.h @@ -0,0 +1,166 @@ +#ifndef _TIME_H +#define _TIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + + +#define __NEED_size_t +#define __NEED_time_t +#define __NEED_clock_t +#define __NEED_struct_timespec + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +#define __NEED_clockid_t +#define __NEED_timer_t +#define __NEED_pid_t +#define __NEED_locale_t +#endif + +#include + +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define __tm_gmtoff tm_gmtoff +#define __tm_zone tm_zone +#endif + +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; + long __tm_gmtoff; + const char *__tm_zone; +}; + +clock_t clock (void); +time_t time (time_t *); +double difftime (time_t, time_t); +time_t mktime (struct tm *); +size_t strftime (char *__restrict, size_t, const char *__restrict, const struct tm *__restrict); +struct tm *gmtime (const time_t *); +struct tm *localtime (const time_t *); +char *asctime (const struct tm *); +char *ctime (const time_t *); +int timespec_get(struct timespec *, int); + +#define CLOCKS_PER_SEC 1000000L + +#define TIME_UTC 1 + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) + +size_t strftime_l (char * __restrict, size_t, const char * __restrict, const struct tm * __restrict, locale_t); + +struct tm *gmtime_r (const time_t *__restrict, struct tm *__restrict); +struct tm *localtime_r (const time_t *__restrict, struct tm *__restrict); +char *asctime_r (const struct tm *__restrict, char *__restrict); +char *ctime_r (const time_t *, char *); + +void tzset (void); + +struct itimerspec { + struct timespec it_interval; + struct timespec it_value; +}; + +#define CLOCK_REALTIME 0 +#define CLOCK_MONOTONIC 1 +#define CLOCK_PROCESS_CPUTIME_ID 2 +#define CLOCK_THREAD_CPUTIME_ID 3 +#define CLOCK_MONOTONIC_RAW 4 +#define CLOCK_REALTIME_COARSE 5 +#define CLOCK_MONOTONIC_COARSE 6 +#define CLOCK_BOOTTIME 7 +#define CLOCK_REALTIME_ALARM 8 +#define CLOCK_BOOTTIME_ALARM 9 +#define CLOCK_SGI_CYCLE 10 +#define CLOCK_TAI 11 + +#define TIMER_ABSTIME 1 + +int nanosleep (const struct timespec *, struct timespec *); +int clock_getres (clockid_t, struct timespec *); +int clock_gettime (clockid_t, struct timespec *); +int clock_settime (clockid_t, const struct timespec *); +int clock_nanosleep (clockid_t, int, const struct timespec *, struct timespec *); +int clock_getcpuclockid (pid_t, clockid_t *); + +struct sigevent; +int timer_create (clockid_t, struct sigevent *__restrict, timer_t *__restrict); +int timer_delete (timer_t); +int timer_settime (timer_t, int, const struct itimerspec *__restrict, struct itimerspec *__restrict); +int timer_gettime (timer_t, struct itimerspec *); +int timer_getoverrun (timer_t); + +extern char *tzname[2]; + +#endif + + +#if defined(_XOPEN_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +char *strptime (const char *__restrict, const char *__restrict, struct tm *__restrict); +extern int daylight; +extern long timezone; +extern int getdate_err; +struct tm *getdate (const char *); +#endif + + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int stime(const time_t *); +time_t timegm(struct tm *); +#endif + +#if _REDIR_TIME64 +__REDIR(time, __time64); +__REDIR(difftime, __difftime64); +__REDIR(mktime, __mktime64); +__REDIR(gmtime, __gmtime64); +__REDIR(localtime, __localtime64); +__REDIR(ctime, __ctime64); +__REDIR(timespec_get, __timespec_get_time64); +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ + || defined(_BSD_SOURCE) +__REDIR(gmtime_r, __gmtime64_r); +__REDIR(localtime_r, __localtime64_r); +__REDIR(ctime_r, __ctime64_r); +__REDIR(nanosleep, __nanosleep_time64); +__REDIR(clock_getres, __clock_getres_time64); +__REDIR(clock_gettime, __clock_gettime64); +__REDIR(clock_settime, __clock_settime64); +__REDIR(clock_nanosleep, __clock_nanosleep_time64); +__REDIR(timer_settime, __timer_settime64); +__REDIR(timer_gettime, __timer_gettime64); +#endif +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +__REDIR(stime, __stime64); +__REDIR(timegm, __timegm_time64); +#endif +#endif + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/c/common/test/includes/standard-library/uchar.h b/c/common/test/includes/standard-library/uchar.h new file mode 100644 index 0000000000..7e5c4d4068 --- /dev/null +++ b/c/common/test/includes/standard-library/uchar.h @@ -0,0 +1,29 @@ +#ifndef _UCHAR_H +#define _UCHAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if __cplusplus < 201103L +typedef unsigned short char16_t; +typedef unsigned char32_t; +#endif + +#define __NEED_mbstate_t +#define __NEED_size_t + +#include +#include + +size_t c16rtomb(char *__restrict, char16_t, mbstate_t *__restrict); +size_t mbrtoc16(char16_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict); + +size_t c32rtomb(char *__restrict, char32_t, mbstate_t *__restrict); +size_t mbrtoc32(char32_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/ucontext.h b/c/common/test/includes/standard-library/ucontext.h new file mode 100644 index 0000000000..0f75712548 --- /dev/null +++ b/c/common/test/includes/standard-library/ucontext.h @@ -0,0 +1,25 @@ +#ifndef _UCONTEXT_H +#define _UCONTEXT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define NGREG (sizeof(gregset_t)/sizeof(greg_t)) +#endif + +struct __ucontext; + +int getcontext(struct __ucontext *); +void makecontext(struct __ucontext *, void (*)(), int, ...); +int setcontext(const struct __ucontext *); +int swapcontext(struct __ucontext *, const struct __ucontext *); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/common/test/includes/standard-library/ulimit.h b/c/common/test/includes/standard-library/ulimit.h new file mode 100644 index 0000000000..efdcd311e5 --- /dev/null +++ b/c/common/test/includes/standard-library/ulimit.h @@ -0,0 +1,17 @@ +#ifndef _ULIMIT_H +#define _ULIMIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define UL_GETFSIZE 1 +#define UL_SETFSIZE 2 + +long ulimit (int, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/unistd.h b/c/common/test/includes/standard-library/unistd.h new file mode 100644 index 0000000000..1306402603 --- /dev/null +++ b/c/common/test/includes/standard-library/unistd.h @@ -0,0 +1,471 @@ +#ifndef _UNISTD_H +#define _UNISTD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#define __NEED_size_t +#define __NEED_ssize_t +#define __NEED_uid_t +#define __NEED_gid_t +#define __NEED_off_t +#define __NEED_pid_t +#define __NEED_intptr_t +#define __NEED_useconds_t + +#include + +int pipe(int [2]); +int pipe2(int [2], int); +int close(int); +int posix_close(int, int); +int dup(int); +int dup2(int, int); +int dup3(int, int, int); +off_t lseek(int, off_t, int); +int fsync(int); +int fdatasync(int); + +ssize_t read(int, void *, size_t); +ssize_t write(int, const void *, size_t); +ssize_t pread(int, void *, size_t, off_t); +ssize_t pwrite(int, const void *, size_t, off_t); + +int chown(const char *, uid_t, gid_t); +int fchown(int, uid_t, gid_t); +int lchown(const char *, uid_t, gid_t); +int fchownat(int, const char *, uid_t, gid_t, int); + +int link(const char *, const char *); +int linkat(int, const char *, int, const char *, int); +int symlink(const char *, const char *); +int symlinkat(const char *, int, const char *); +ssize_t readlink(const char *__restrict, char *__restrict, size_t); +ssize_t readlinkat(int, const char *__restrict, char *__restrict, size_t); +int unlink(const char *); +int unlinkat(int, const char *, int); +int rmdir(const char *); +int truncate(const char *, off_t); +int ftruncate(int, off_t); + +#define F_OK 0 +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 + +int access(const char *, int); +int faccessat(int, const char *, int, int); + +int chdir(const char *); +int fchdir(int); +char *getcwd(char *, size_t); + +unsigned alarm(unsigned); +unsigned sleep(unsigned); +int pause(void); + +pid_t fork(void); +pid_t _Fork(void); +int execve(const char *, char *const [], char *const []); +int execv(const char *, char *const []); +int execle(const char *, const char *, ...); +int execl(const char *, const char *, ...); +int execvp(const char *, char *const []); +int execlp(const char *, const char *, ...); +int fexecve(int, char *const [], char *const []); +_Noreturn void _exit(int); + +pid_t getpid(void); +pid_t getppid(void); +pid_t getpgrp(void); +pid_t getpgid(pid_t); +int setpgid(pid_t, pid_t); +pid_t setsid(void); +pid_t getsid(pid_t); +char *ttyname(int); +int ttyname_r(int, char *, size_t); +int isatty(int); +pid_t tcgetpgrp(int); +int tcsetpgrp(int, pid_t); + +uid_t getuid(void); +uid_t geteuid(void); +gid_t getgid(void); +gid_t getegid(void); +int getgroups(int, gid_t []); +int setuid(uid_t); +int seteuid(uid_t); +int setgid(gid_t); +int setegid(gid_t); + +char *getlogin(void); +int getlogin_r(char *, size_t); +int gethostname(char *, size_t); +char *ctermid(char *); + +int getopt(int, char * const [], const char *); +extern char *optarg; +extern int optind, opterr, optopt; + +long pathconf(const char *, int); +long fpathconf(int, int); +long sysconf(int); +size_t confstr(int, char *, size_t); + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define F_ULOCK 0 +#define F_LOCK 1 +#define F_TLOCK 2 +#define F_TEST 3 +int setreuid(uid_t, uid_t); +int setregid(gid_t, gid_t); +int lockf(int, int, off_t); +long gethostid(void); +int nice(int); +void sync(void); +pid_t setpgrp(void); +char *crypt(const char *, const char *); +void encrypt(char *, int); +void swab(const void *__restrict, void *__restrict, ssize_t); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) +int usleep(unsigned); +unsigned ualarm(unsigned, unsigned); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define L_SET 0 +#define L_INCR 1 +#define L_XTND 2 +int brk(void *); +void *sbrk(intptr_t); +pid_t vfork(void); +int vhangup(void); +int chroot(const char *); +int getpagesize(void); +int getdtablesize(void); +int sethostname(const char *, size_t); +int getdomainname(char *, size_t); +int setdomainname(const char *, size_t); +int setgroups(size_t, const gid_t *); +char *getpass(const char *); +int daemon(int, int); +void setusershell(void); +void endusershell(void); +char *getusershell(void); +int acct(const char *); +long syscall(long, ...); +int execvpe(const char *, char *const [], char *const []); +int issetugid(void); +int getentropy(void *, size_t); +extern int optreset; +#endif + +#ifdef _GNU_SOURCE +extern char **environ; +int setresuid(uid_t, uid_t, uid_t); +int setresgid(gid_t, gid_t, gid_t); +int getresuid(uid_t *, uid_t *, uid_t *); +int getresgid(gid_t *, gid_t *, gid_t *); +char *get_current_dir_name(void); +int syncfs(int); +int euidaccess(const char *, int); +int eaccess(const char *, int); +ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); +pid_t gettid(void); +#endif + +#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE) +#define lseek64 lseek +#define pread64 pread +#define pwrite64 pwrite +#define truncate64 truncate +#define ftruncate64 ftruncate +#define lockf64 lockf +#define off64_t off_t +#endif + +#define POSIX_CLOSE_RESTART 0 + +#define _XOPEN_VERSION 700 +#define _XOPEN_UNIX 1 +#define _XOPEN_ENH_I18N 1 + +#define _POSIX_VERSION 200809L +#define _POSIX2_VERSION _POSIX_VERSION + +#define _POSIX_ADVISORY_INFO _POSIX_VERSION +#define _POSIX_CHOWN_RESTRICTED 1 +#define _POSIX_IPV6 _POSIX_VERSION +#define _POSIX_JOB_CONTROL 1 +#define _POSIX_MAPPED_FILES _POSIX_VERSION +#define _POSIX_MEMLOCK _POSIX_VERSION +#define _POSIX_MEMLOCK_RANGE _POSIX_VERSION +#define _POSIX_MEMORY_PROTECTION _POSIX_VERSION +#define _POSIX_MESSAGE_PASSING _POSIX_VERSION +#define _POSIX_FSYNC _POSIX_VERSION +#define _POSIX_NO_TRUNC 1 +#define _POSIX_RAW_SOCKETS _POSIX_VERSION +#define _POSIX_REALTIME_SIGNALS _POSIX_VERSION +#define _POSIX_REGEXP 1 +#define _POSIX_SAVED_IDS 1 +#define _POSIX_SHELL 1 +#define _POSIX_SPAWN _POSIX_VERSION +#define _POSIX_VDISABLE 0 + +#define _POSIX_THREADS _POSIX_VERSION +#define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION +#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION +#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION +#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION +#define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION +#define _POSIX_THREAD_CPUTIME _POSIX_VERSION +#define _POSIX_TIMERS _POSIX_VERSION +#define _POSIX_TIMEOUTS _POSIX_VERSION +#define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION +#define _POSIX_CPUTIME _POSIX_VERSION +#define _POSIX_CLOCK_SELECTION _POSIX_VERSION +#define _POSIX_BARRIERS _POSIX_VERSION +#define _POSIX_SPIN_LOCKS _POSIX_VERSION +#define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION +#define _POSIX_ASYNCHRONOUS_IO _POSIX_VERSION +#define _POSIX_SEMAPHORES _POSIX_VERSION +#define _POSIX_SHARED_MEMORY_OBJECTS _POSIX_VERSION + +#define _POSIX2_C_BIND _POSIX_VERSION + +#include + + + +#define _PC_LINK_MAX 0 +#define _PC_MAX_CANON 1 +#define _PC_MAX_INPUT 2 +#define _PC_NAME_MAX 3 +#define _PC_PATH_MAX 4 +#define _PC_PIPE_BUF 5 +#define _PC_CHOWN_RESTRICTED 6 +#define _PC_NO_TRUNC 7 +#define _PC_VDISABLE 8 +#define _PC_SYNC_IO 9 +#define _PC_ASYNC_IO 10 +#define _PC_PRIO_IO 11 +#define _PC_SOCK_MAXBUF 12 +#define _PC_FILESIZEBITS 13 +#define _PC_REC_INCR_XFER_SIZE 14 +#define _PC_REC_MAX_XFER_SIZE 15 +#define _PC_REC_MIN_XFER_SIZE 16 +#define _PC_REC_XFER_ALIGN 17 +#define _PC_ALLOC_SIZE_MIN 18 +#define _PC_SYMLINK_MAX 19 +#define _PC_2_SYMLINKS 20 + +#define _SC_ARG_MAX 0 +#define _SC_CHILD_MAX 1 +#define _SC_CLK_TCK 2 +#define _SC_NGROUPS_MAX 3 +#define _SC_OPEN_MAX 4 +#define _SC_STREAM_MAX 5 +#define _SC_TZNAME_MAX 6 +#define _SC_JOB_CONTROL 7 +#define _SC_SAVED_IDS 8 +#define _SC_REALTIME_SIGNALS 9 +#define _SC_PRIORITY_SCHEDULING 10 +#define _SC_TIMERS 11 +#define _SC_ASYNCHRONOUS_IO 12 +#define _SC_PRIORITIZED_IO 13 +#define _SC_SYNCHRONIZED_IO 14 +#define _SC_FSYNC 15 +#define _SC_MAPPED_FILES 16 +#define _SC_MEMLOCK 17 +#define _SC_MEMLOCK_RANGE 18 +#define _SC_MEMORY_PROTECTION 19 +#define _SC_MESSAGE_PASSING 20 +#define _SC_SEMAPHORES 21 +#define _SC_SHARED_MEMORY_OBJECTS 22 +#define _SC_AIO_LISTIO_MAX 23 +#define _SC_AIO_MAX 24 +#define _SC_AIO_PRIO_DELTA_MAX 25 +#define _SC_DELAYTIMER_MAX 26 +#define _SC_MQ_OPEN_MAX 27 +#define _SC_MQ_PRIO_MAX 28 +#define _SC_VERSION 29 +#define _SC_PAGE_SIZE 30 +#define _SC_PAGESIZE 30 /* !! */ +#define _SC_RTSIG_MAX 31 +#define _SC_SEM_NSEMS_MAX 32 +#define _SC_SEM_VALUE_MAX 33 +#define _SC_SIGQUEUE_MAX 34 +#define _SC_TIMER_MAX 35 +#define _SC_BC_BASE_MAX 36 +#define _SC_BC_DIM_MAX 37 +#define _SC_BC_SCALE_MAX 38 +#define _SC_BC_STRING_MAX 39 +#define _SC_COLL_WEIGHTS_MAX 40 +#define _SC_EXPR_NEST_MAX 42 +#define _SC_LINE_MAX 43 +#define _SC_RE_DUP_MAX 44 +#define _SC_2_VERSION 46 +#define _SC_2_C_BIND 47 +#define _SC_2_C_DEV 48 +#define _SC_2_FORT_DEV 49 +#define _SC_2_FORT_RUN 50 +#define _SC_2_SW_DEV 51 +#define _SC_2_LOCALEDEF 52 +#define _SC_UIO_MAXIOV 60 /* !! */ +#define _SC_IOV_MAX 60 +#define _SC_THREADS 67 +#define _SC_THREAD_SAFE_FUNCTIONS 68 +#define _SC_GETGR_R_SIZE_MAX 69 +#define _SC_GETPW_R_SIZE_MAX 70 +#define _SC_LOGIN_NAME_MAX 71 +#define _SC_TTY_NAME_MAX 72 +#define _SC_THREAD_DESTRUCTOR_ITERATIONS 73 +#define _SC_THREAD_KEYS_MAX 74 +#define _SC_THREAD_STACK_MIN 75 +#define _SC_THREAD_THREADS_MAX 76 +#define _SC_THREAD_ATTR_STACKADDR 77 +#define _SC_THREAD_ATTR_STACKSIZE 78 +#define _SC_THREAD_PRIORITY_SCHEDULING 79 +#define _SC_THREAD_PRIO_INHERIT 80 +#define _SC_THREAD_PRIO_PROTECT 81 +#define _SC_THREAD_PROCESS_SHARED 82 +#define _SC_NPROCESSORS_CONF 83 +#define _SC_NPROCESSORS_ONLN 84 +#define _SC_PHYS_PAGES 85 +#define _SC_AVPHYS_PAGES 86 +#define _SC_ATEXIT_MAX 87 +#define _SC_PASS_MAX 88 +#define _SC_XOPEN_VERSION 89 +#define _SC_XOPEN_XCU_VERSION 90 +#define _SC_XOPEN_UNIX 91 +#define _SC_XOPEN_CRYPT 92 +#define _SC_XOPEN_ENH_I18N 93 +#define _SC_XOPEN_SHM 94 +#define _SC_2_CHAR_TERM 95 +#define _SC_2_UPE 97 +#define _SC_XOPEN_XPG2 98 +#define _SC_XOPEN_XPG3 99 +#define _SC_XOPEN_XPG4 100 +#define _SC_NZERO 109 +#define _SC_XBS5_ILP32_OFF32 125 +#define _SC_XBS5_ILP32_OFFBIG 126 +#define _SC_XBS5_LP64_OFF64 127 +#define _SC_XBS5_LPBIG_OFFBIG 128 +#define _SC_XOPEN_LEGACY 129 +#define _SC_XOPEN_REALTIME 130 +#define _SC_XOPEN_REALTIME_THREADS 131 +#define _SC_ADVISORY_INFO 132 +#define _SC_BARRIERS 133 +#define _SC_CLOCK_SELECTION 137 +#define _SC_CPUTIME 138 +#define _SC_THREAD_CPUTIME 139 +#define _SC_MONOTONIC_CLOCK 149 +#define _SC_READER_WRITER_LOCKS 153 +#define _SC_SPIN_LOCKS 154 +#define _SC_REGEXP 155 +#define _SC_SHELL 157 +#define _SC_SPAWN 159 +#define _SC_SPORADIC_SERVER 160 +#define _SC_THREAD_SPORADIC_SERVER 161 +#define _SC_TIMEOUTS 164 +#define _SC_TYPED_MEMORY_OBJECTS 165 +#define _SC_2_PBS 168 +#define _SC_2_PBS_ACCOUNTING 169 +#define _SC_2_PBS_LOCATE 170 +#define _SC_2_PBS_MESSAGE 171 +#define _SC_2_PBS_TRACK 172 +#define _SC_SYMLOOP_MAX 173 +#define _SC_STREAMS 174 +#define _SC_2_PBS_CHECKPOINT 175 +#define _SC_V6_ILP32_OFF32 176 +#define _SC_V6_ILP32_OFFBIG 177 +#define _SC_V6_LP64_OFF64 178 +#define _SC_V6_LPBIG_OFFBIG 179 +#define _SC_HOST_NAME_MAX 180 +#define _SC_TRACE 181 +#define _SC_TRACE_EVENT_FILTER 182 +#define _SC_TRACE_INHERIT 183 +#define _SC_TRACE_LOG 184 + +#define _SC_IPV6 235 +#define _SC_RAW_SOCKETS 236 +#define _SC_V7_ILP32_OFF32 237 +#define _SC_V7_ILP32_OFFBIG 238 +#define _SC_V7_LP64_OFF64 239 +#define _SC_V7_LPBIG_OFFBIG 240 +#define _SC_SS_REPL_MAX 241 +#define _SC_TRACE_EVENT_NAME_MAX 242 +#define _SC_TRACE_NAME_MAX 243 +#define _SC_TRACE_SYS_MAX 244 +#define _SC_TRACE_USER_EVENT_MAX 245 +#define _SC_XOPEN_STREAMS 246 +#define _SC_THREAD_ROBUST_PRIO_INHERIT 247 +#define _SC_THREAD_ROBUST_PRIO_PROTECT 248 + +#define _CS_PATH 0 +#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1 +#define _CS_GNU_LIBC_VERSION 2 +#define _CS_GNU_LIBPTHREAD_VERSION 3 +#define _CS_POSIX_V5_WIDTH_RESTRICTED_ENVS 4 +#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS 5 + +#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS 1116 +#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS 1117 +#define _CS_POSIX_V6_ILP32_OFF32_LIBS 1118 +#define _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS 1119 +#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS 1120 +#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS 1121 +#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS 1122 +#define _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS 1123 +#define _CS_POSIX_V6_LP64_OFF64_CFLAGS 1124 +#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS 1125 +#define _CS_POSIX_V6_LP64_OFF64_LIBS 1126 +#define _CS_POSIX_V6_LP64_OFF64_LINTFLAGS 1127 +#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS 1128 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS 1129 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS 1130 +#define _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS 1131 +#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS 1132 +#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS 1133 +#define _CS_POSIX_V7_ILP32_OFF32_LIBS 1134 +#define _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS 1135 +#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS 1136 +#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS 1137 +#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS 1138 +#define _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS 1139 +#define _CS_POSIX_V7_LP64_OFF64_CFLAGS 1140 +#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS 1141 +#define _CS_POSIX_V7_LP64_OFF64_LIBS 1142 +#define _CS_POSIX_V7_LP64_OFF64_LINTFLAGS 1143 +#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS 1144 +#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS 1145 +#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS 1146 +#define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS 1147 +#define _CS_V6_ENV 1148 +#define _CS_V7_ENV 1149 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/utime.h b/c/common/test/includes/standard-library/utime.h new file mode 100644 index 0000000000..5755bd53ee --- /dev/null +++ b/c/common/test/includes/standard-library/utime.h @@ -0,0 +1,29 @@ +#ifndef _UTIME_H +#define _UTIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_time_t + +#include + +struct utimbuf { + time_t actime; + time_t modtime; +}; + +int utime (const char *, const struct utimbuf *); + +#if _REDIR_TIME64 +__REDIR(utime, __utime64); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/utmp.h b/c/common/test/includes/standard-library/utmp.h new file mode 100644 index 0000000000..48a400d84d --- /dev/null +++ b/c/common/test/includes/standard-library/utmp.h @@ -0,0 +1,52 @@ +#ifndef _UTMP_H +#define _UTMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define ACCOUNTING 9 +#define UT_NAMESIZE 32 +#define UT_HOSTSIZE 256 +#define UT_LINESIZE 32 + +struct lastlog { + time_t ll_time; + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; +}; + +#define ut_time ut_tv.tv_sec +#define ut_name ut_user +#define ut_addr ut_addr_v6[0] +#define utmp utmpx +#define e_exit __e_exit +#define e_termination __e_termination + +void endutent(void); +struct utmp *getutent(void); +struct utmp *getutid(const struct utmp *); +struct utmp *getutline(const struct utmp *); +struct utmp *pututline(const struct utmp *); +void setutent(void); + +void updwtmp(const char *, const struct utmp *); +int utmpname(const char *); + +int login_tty(int); + +#define _PATH_UTMP "/dev/null/utmp" +#define _PATH_WTMP "/dev/null/wtmp" + +#define UTMP_FILE _PATH_UTMP +#define WTMP_FILE _PATH_WTMP +#define UTMP_FILENAME _PATH_UTMP +#define WTMP_FILENAME _PATH_WTMP + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/utmpx.h b/c/common/test/includes/standard-library/utmpx.h new file mode 100644 index 0000000000..b293f427e6 --- /dev/null +++ b/c/common/test/includes/standard-library/utmpx.h @@ -0,0 +1,67 @@ +#ifndef _UTMPX_H +#define _UTMPX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_pid_t +#define __NEED_time_t +#define __NEED_suseconds_t +#define __NEED_struct_timeval + +#include + +struct utmpx { + short ut_type; + short __ut_pad1; + pid_t ut_pid; + char ut_line[32]; + char ut_id[4]; + char ut_user[32]; + char ut_host[256]; + struct { + short __e_termination; + short __e_exit; + } ut_exit; +#if __BYTE_ORDER == 1234 + int ut_session, __ut_pad2; +#else + int __ut_pad2, ut_session; +#endif + struct timeval ut_tv; + unsigned ut_addr_v6[4]; + char __unused[20]; +}; + +void endutxent(void); +struct utmpx *getutxent(void); +struct utmpx *getutxid(const struct utmpx *); +struct utmpx *getutxline(const struct utmpx *); +struct utmpx *pututxline(const struct utmpx *); +void setutxent(void); + +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define e_exit __e_exit +#define e_termination __e_termination +void updwtmpx(const char *, const struct utmpx *); +int utmpxname(const char *); +#endif + +#define EMPTY 0 +#define RUN_LVL 1 +#define BOOT_TIME 2 +#define NEW_TIME 3 +#define OLD_TIME 4 +#define INIT_PROCESS 5 +#define LOGIN_PROCESS 6 +#define USER_PROCESS 7 +#define DEAD_PROCESS 8 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/values.h b/c/common/test/includes/standard-library/values.h new file mode 100644 index 0000000000..fe4949f85e --- /dev/null +++ b/c/common/test/includes/standard-library/values.h @@ -0,0 +1,39 @@ +#ifndef _VALUES_H +#define _VALUES_H + +#include + +#define CHARBITS (sizeof(char) * 8) +#define SHORTBITS (sizeof(short) * 8) +#define INTBITS (sizeof(int) * 8) +#define LONGBITS (sizeof(long) * 8) +#define PTRBITS (sizeof(char *) * 8) +#define DOUBLEBITS (sizeof(double) * 8) +#define FLOATBITS (sizeof(float) * 8) + +#define MINSHORT SHRT_MIN +#define MININT INT_MIN +#define MINLONG LONG_MIN + +#define MAXSHORT SHRT_MAX +#define MAXINT INT_MAX +#define MAXLONG LONG_MAX + +#define HIBITS MINSHORT +#define HIBITL MINLONG + +#include + +#define MAXDOUBLE DBL_MAX +#undef MAXFLOAT +#define MAXFLOAT FLT_MAX +#define MINDOUBLE DBL_MIN +#define MINFLOAT FLT_MIN +#define DMINEXP DBL_MIN_EXP +#define FMINEXP FLT_MIN_EXP +#define DMAXEXP DBL_MAX_EXP +#define FMAXEXP FLT_MAX_EXP + +#define BITSPERBYTE CHAR_BIT + +#endif diff --git a/c/common/test/includes/standard-library/wait.h b/c/common/test/includes/standard-library/wait.h new file mode 100644 index 0000000000..98396e2d20 --- /dev/null +++ b/c/common/test/includes/standard-library/wait.h @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff --git a/c/common/test/includes/standard-library/wchar.h b/c/common/test/includes/standard-library/wchar.h new file mode 100644 index 0000000000..88eb55b18c --- /dev/null +++ b/c/common/test/includes/standard-library/wchar.h @@ -0,0 +1,205 @@ +#ifndef _WCHAR_H +#define _WCHAR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_FILE +#define __NEED___isoc_va_list +#define __NEED_size_t +#define __NEED_wchar_t +#define __NEED_wint_t +#define __NEED_mbstate_t + +#if __STDC_VERSION__ < 201112L +#define __NEED_struct__IO_FILE +#endif + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_locale_t +#define __NEED_va_list +#endif + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_wctype_t +#endif + +#include + +#if L'\0'-1 > 0 +#define WCHAR_MAX (0xffffffffu+L'\0') +#define WCHAR_MIN (0+L'\0') +#else +#define WCHAR_MAX (0x7fffffff+L'\0') +#define WCHAR_MIN (-1-0x7fffffff+L'\0') +#endif + +#ifdef __cplusplus +#define NULL 0L +#else +#define NULL ((void*)0) +#endif + +#undef WEOF +#define WEOF 0xffffffffU + +wchar_t *wcscpy (wchar_t *__restrict, const wchar_t *__restrict); +wchar_t *wcsncpy (wchar_t *__restrict, const wchar_t *__restrict, size_t); + +wchar_t *wcscat (wchar_t *__restrict, const wchar_t *__restrict); +wchar_t *wcsncat (wchar_t *__restrict, const wchar_t *__restrict, size_t); + +int wcscmp (const wchar_t *, const wchar_t *); +int wcsncmp (const wchar_t *, const wchar_t *, size_t); + +int wcscoll(const wchar_t *, const wchar_t *); +size_t wcsxfrm (wchar_t *__restrict, const wchar_t *__restrict, size_t); + +wchar_t *wcschr (const wchar_t *, wchar_t); +wchar_t *wcsrchr (const wchar_t *, wchar_t); + +size_t wcscspn (const wchar_t *, const wchar_t *); +size_t wcsspn (const wchar_t *, const wchar_t *); +wchar_t *wcspbrk (const wchar_t *, const wchar_t *); + +wchar_t *wcstok (wchar_t *__restrict, const wchar_t *__restrict, wchar_t **__restrict); + +size_t wcslen (const wchar_t *); + +wchar_t *wcsstr (const wchar_t *__restrict, const wchar_t *__restrict); +wchar_t *wcswcs (const wchar_t *, const wchar_t *); + +wchar_t *wmemchr (const wchar_t *, wchar_t, size_t); +int wmemcmp (const wchar_t *, const wchar_t *, size_t); +wchar_t *wmemcpy (wchar_t *__restrict, const wchar_t *__restrict, size_t); +wchar_t *wmemmove (wchar_t *, const wchar_t *, size_t); +wchar_t *wmemset (wchar_t *, wchar_t, size_t); + +wint_t btowc (int); +int wctob (wint_t); + +int mbsinit (const mbstate_t *); +size_t mbrtowc (wchar_t *__restrict, const char *__restrict, size_t, mbstate_t *__restrict); +size_t wcrtomb (char *__restrict, wchar_t, mbstate_t *__restrict); + +size_t mbrlen (const char *__restrict, size_t, mbstate_t *__restrict); + +size_t mbsrtowcs (wchar_t *__restrict, const char **__restrict, size_t, mbstate_t *__restrict); +size_t wcsrtombs (char *__restrict, const wchar_t **__restrict, size_t, mbstate_t *__restrict); + +float wcstof (const wchar_t *__restrict, wchar_t **__restrict); +double wcstod (const wchar_t *__restrict, wchar_t **__restrict); +long double wcstold (const wchar_t *__restrict, wchar_t **__restrict); + +long wcstol (const wchar_t *__restrict, wchar_t **__restrict, int); +unsigned long wcstoul (const wchar_t *__restrict, wchar_t **__restrict, int); + +long long wcstoll (const wchar_t *__restrict, wchar_t **__restrict, int); +unsigned long long wcstoull (const wchar_t *__restrict, wchar_t **__restrict, int); + + + +int fwide (FILE *, int); + + +int wprintf (const wchar_t *__restrict, ...); +int fwprintf (FILE *__restrict, const wchar_t *__restrict, ...); +int swprintf (wchar_t *__restrict, size_t, const wchar_t *__restrict, ...); + +int vwprintf (const wchar_t *__restrict, __isoc_va_list); +int vfwprintf (FILE *__restrict, const wchar_t *__restrict, __isoc_va_list); +int vswprintf (wchar_t *__restrict, size_t, const wchar_t *__restrict, __isoc_va_list); + +int wscanf (const wchar_t *__restrict, ...); +int fwscanf (FILE *__restrict, const wchar_t *__restrict, ...); +int swscanf (const wchar_t *__restrict, const wchar_t *__restrict, ...); + +int vwscanf (const wchar_t *__restrict, __isoc_va_list); +int vfwscanf (FILE *__restrict, const wchar_t *__restrict, __isoc_va_list); +int vswscanf (const wchar_t *__restrict, const wchar_t *__restrict, __isoc_va_list); + +wint_t fgetwc (FILE *); +wint_t getwc (FILE *); +wint_t getwchar (void); + +wint_t fputwc (wchar_t, FILE *); +wint_t putwc (wchar_t, FILE *); +wint_t putwchar (wchar_t); + +wchar_t *fgetws (wchar_t *__restrict, int, FILE *__restrict); +int fputws (const wchar_t *__restrict, FILE *__restrict); + +wint_t ungetwc (wint_t, FILE *); + +struct tm; +size_t wcsftime (wchar_t *__restrict, size_t, const wchar_t *__restrict, const struct tm *__restrict); + +#undef iswdigit + +#if defined(_GNU_SOURCE) +wint_t fgetwc_unlocked (FILE *); +wint_t getwc_unlocked (FILE *); +wint_t getwchar_unlocked (void); +wint_t fputwc_unlocked (wchar_t, FILE *); +wint_t putwc_unlocked (wchar_t, FILE *); +wint_t putwchar_unlocked (wchar_t); +wchar_t *fgetws_unlocked (wchar_t *__restrict, int, FILE *__restrict); +int fputws_unlocked (const wchar_t *__restrict, FILE *__restrict); +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +size_t wcsftime_l (wchar_t *__restrict, size_t, const wchar_t *__restrict, const struct tm *__restrict, locale_t); +#endif + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +FILE *open_wmemstream(wchar_t **, size_t *); +size_t mbsnrtowcs(wchar_t *__restrict, const char **__restrict, size_t, size_t, mbstate_t *__restrict); +size_t wcsnrtombs(char *__restrict, const wchar_t **__restrict, size_t, size_t, mbstate_t *__restrict); +wchar_t *wcsdup(const wchar_t *); +size_t wcsnlen (const wchar_t *, size_t); +wchar_t *wcpcpy (wchar_t *__restrict, const wchar_t *__restrict); +wchar_t *wcpncpy (wchar_t *__restrict, const wchar_t *__restrict, size_t); +int wcscasecmp(const wchar_t *, const wchar_t *); +int wcscasecmp_l(const wchar_t *, const wchar_t *, locale_t); +int wcsncasecmp(const wchar_t *, const wchar_t *, size_t); +int wcsncasecmp_l(const wchar_t *, const wchar_t *, size_t, locale_t); +int wcscoll_l(const wchar_t *, const wchar_t *, locale_t); +size_t wcsxfrm_l(wchar_t *__restrict, const wchar_t *__restrict, size_t, locale_t); +#endif + +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +int wcwidth (wchar_t); +int wcswidth (const wchar_t *, size_t); +int iswalnum(wint_t); +int iswalpha(wint_t); +int iswblank(wint_t); +int iswcntrl(wint_t); +int iswdigit(wint_t); +int iswgraph(wint_t); +int iswlower(wint_t); +int iswprint(wint_t); +int iswpunct(wint_t); +int iswspace(wint_t); +int iswupper(wint_t); +int iswxdigit(wint_t); +int iswctype(wint_t, wctype_t); +wint_t towlower(wint_t); +wint_t towupper(wint_t); +wctype_t wctype(const char *); + +#ifndef __cplusplus +#undef iswdigit +#define iswdigit(a) (0 ? iswdigit(a) : ((unsigned)(a)-'0') < 10) +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/wctype.h b/c/common/test/includes/standard-library/wctype.h new file mode 100644 index 0000000000..bc2420d3fd --- /dev/null +++ b/c/common/test/includes/standard-library/wctype.h @@ -0,0 +1,79 @@ +#ifndef _WCTYPE_H +#define _WCTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_wint_t +#define __NEED_wctype_t + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) +#define __NEED_locale_t +#endif + +#include + +typedef const int * wctrans_t; + +#undef WEOF +#define WEOF 0xffffffffU + +#undef iswdigit + +int iswalnum(wint_t); +int iswalpha(wint_t); +int iswblank(wint_t); +int iswcntrl(wint_t); +int iswdigit(wint_t); +int iswgraph(wint_t); +int iswlower(wint_t); +int iswprint(wint_t); +int iswpunct(wint_t); +int iswspace(wint_t); +int iswupper(wint_t); +int iswxdigit(wint_t); +int iswctype(wint_t, wctype_t); +wint_t towctrans(wint_t, wctrans_t); +wint_t towlower(wint_t); +wint_t towupper(wint_t); +wctrans_t wctrans(const char *); +wctype_t wctype(const char *); + +#ifndef __cplusplus +#undef iswdigit +#define iswdigit(a) (0 ? iswdigit(a) : ((unsigned)(a)-'0') < 10) +#endif + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + +int iswalnum_l(wint_t, locale_t); +int iswalpha_l(wint_t, locale_t); +int iswblank_l(wint_t, locale_t); +int iswcntrl_l(wint_t, locale_t); +int iswdigit_l(wint_t, locale_t); +int iswgraph_l(wint_t, locale_t); +int iswlower_l(wint_t, locale_t); +int iswprint_l(wint_t, locale_t); +int iswpunct_l(wint_t, locale_t); +int iswspace_l(wint_t, locale_t); +int iswupper_l(wint_t, locale_t); +int iswxdigit_l(wint_t, locale_t); +int iswctype_l(wint_t, wctype_t, locale_t); +wint_t towlower_l(wint_t, locale_t); +wint_t towupper_l(wint_t, locale_t); +wint_t towctrans_l(wint_t, wctrans_t, locale_t); +wctrans_t wctrans_l(const char *, locale_t); +wctype_t wctype_l(const char *, locale_t); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/includes/standard-library/wordexp.h b/c/common/test/includes/standard-library/wordexp.h new file mode 100644 index 0000000000..5460002dee --- /dev/null +++ b/c/common/test/includes/standard-library/wordexp.h @@ -0,0 +1,41 @@ +#ifndef _WORDEXP_H +#define _WORDEXP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define __NEED_size_t + +#include + +#define WRDE_DOOFFS 1 +#define WRDE_APPEND 2 +#define WRDE_NOCMD 4 +#define WRDE_REUSE 8 +#define WRDE_SHOWERR 16 +#define WRDE_UNDEF 32 + +typedef struct { + size_t we_wordc; + char **we_wordv; + size_t we_offs; +} wordexp_t; + +#define WRDE_NOSYS -1 +#define WRDE_NOSPACE 1 +#define WRDE_BADCHAR 2 +#define WRDE_BADVAL 3 +#define WRDE_CMDSUB 4 +#define WRDE_SYNTAX 5 + +int wordexp (const char *__restrict, wordexp_t *__restrict, int); +void wordfree (wordexp_t *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/common/test/qlpack.yml b/c/common/test/qlpack.yml new file mode 100644 index 0000000000..cade2e140a --- /dev/null +++ b/c/common/test/qlpack.yml @@ -0,0 +1,4 @@ +name: common-c-coding-standards-tests +version: 2.0.0 +libraryPathDependencies: common-c-coding-standards +extractor: cpp diff --git a/c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.expected b/c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.expected new file mode 100644 index 0000000000..47b81d0c4f --- /dev/null +++ b/c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.expected @@ -0,0 +1,10 @@ +| test.c:6:3:6:8 | call to printf | Access of closed filestdoutwhich was closed at $@ | test.c:4:3:4:8 | call to fclose | this location. | +| test.c:7:3:7:6 | call to puts | Access of closed filestdoutwhich was closed at $@ | test.c:4:3:4:8 | call to fclose | this location. | +| test.c:16:13:16:18 | stderr | Access of closed filestderrwhich was closed at $@ | test.c:13:3:13:8 | call to fclose | this location. | +| test.c:17:3:17:8 | call to perror | Access of closed filestderrwhich was closed at $@ | test.c:13:3:13:8 | call to fclose | this location. | +| test.c:24:8:24:12 | stdin | Access of closed filestdinwhich was closed at $@ | test.c:22:3:22:8 | call to fclose | this location. | +| test.c:25:3:25:9 | call to getchar | Access of closed filestdinwhich was closed at $@ | test.c:22:3:22:8 | call to fclose | this location. | +| test.c:34:18:34:18 | f | Access of closed filefwhich was closed at $@ | test.c:31:3:31:8 | call to fclose | this location. | +| test.c:35:15:35:15 | f | Access of closed filefwhich was closed at $@ | test.c:31:3:31:8 | call to fclose | this location. | +| test.c:70:11:70:12 | fp | Access of closed filefpwhich was closed at $@ | test.c:69:3:69:8 | call to fclose | this location. | +| test.c:71:7:71:8 | fp | Access of closed filefpwhich was closed at $@ | test.c:69:3:69:8 | call to fclose | this location. | diff --git a/c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.ql b/c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.ql new file mode 100644 index 0000000000..430e258ae0 --- /dev/null +++ b/c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.donotaccessaclosedfile.DoNotAccessAClosedFile diff --git a/c/common/test/rules/donotaccessaclosedfile/test.c b/c/common/test/rules/donotaccessaclosedfile/test.c new file mode 100644 index 0000000000..b24ff1137c --- /dev/null +++ b/c/common/test/rules/donotaccessaclosedfile/test.c @@ -0,0 +1,73 @@ +#include + +int f1(void) { + fclose(stdout); + + printf(""); // NON_COMPLIANT + puts(""); // NON_COMPLIANT + perror(""); // COMPLIANT + return 0; +} + +int f2(void) { + fclose(stderr); + + puts(""); // COMPLIANT + fputs("", stderr); // NON_COMPLIANT + perror(""); // NON_COMPLIANT + return 0; +} + +int f3(void) { + fclose(stdin); + + getc(stdin); // NON_COMPLIANT + getchar(); // NON_COMPLIANT + return 0; +} + +int f4(void) { + FILE *f = fopen("myfile", "rw"); + fclose(f); + + printf(""); // COMPLIANT + fputs("write", f); // NON_COMPLIANT + return getc(f); // NON_COMPLIANT +} + +int f5(void) { + FILE *f = fopen("myfile", "rw"); + + int c; + while ((c = getchar())) { // COMPLIANT + if (c == EOF) { + fclose(f); + break; + } + } + + return 0; +} + +int f6(void) { + FILE *f = fopen("myfile1", "rw"); + FILE *g = fopen("myfile2", "rw"); + fclose(f); + f = g; // COMPLIANT + + fputs("write", f); // COMPLIANT + return 0; +} + +int f7(void) { + FILE *fp; + void *p; + fp = fopen("myfile", "w"); + if (fp == NULL) { + return -1; + } + fclose(fp); + fprintf(fp, ""); // NON_COMPLIANT + p = fp; // NON_COMPLIANT + return 0; +} \ No newline at end of file diff --git a/c/common/test/rules/hashoperatorsused/HashOperatorsUsed.expected b/c/common/test/rules/hashoperatorsused/HashOperatorsUsed.expected new file mode 100644 index 0000000000..e844aafb01 --- /dev/null +++ b/c/common/test/rules/hashoperatorsused/HashOperatorsUsed.expected @@ -0,0 +1,4 @@ +| test.c:9:1:9:22 | #define MACROFIVE(X) #X | Macro definition uses the # or ## operator. | +| test.c:11:1:11:26 | #define MACROSIX(X,Y) X ## Y | Macro definition uses the # or ## operator. | +| test.c:13:1:13:29 | #define MACROSEVEN "##'" #"#" | Macro definition uses the # or ## operator. | +| test.c:15:1:15:28 | #define MACROEIGHT '##' #"#" | Macro definition uses the # or ## operator. | diff --git a/c/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql b/c/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql new file mode 100644 index 0000000000..d0ead0b289 --- /dev/null +++ b/c/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.hashoperatorsused.HashOperatorsUsed diff --git a/cpp/autosar/test/rules/M16-3-2/test.cpp b/c/common/test/rules/hashoperatorsused/test.c similarity index 100% rename from cpp/autosar/test/rules/M16-3-2/test.cpp rename to c/common/test/rules/hashoperatorsused/test.c diff --git a/c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected b/c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected new file mode 100644 index 0000000000..3f9791e385 --- /dev/null +++ b/c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected @@ -0,0 +1,2 @@ +| test.c:16:7:16:11 | call to fread | Missing call to positioning function before $@. | test.c:14:7:14:12 | call to fwrite | call to fread | +| test.c:32:7:32:11 | call to fread | Missing call to positioning function before $@. | test.c:30:7:30:12 | call to fwrite | call to fread | diff --git a/c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.ql b/c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.ql new file mode 100644 index 0000000000..164aa6ed96 --- /dev/null +++ b/c/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.iofstreammissingpositioning.IOFstreamMissingPositioning diff --git a/c/common/test/rules/iofstreammissingpositioning/test.c b/c/common/test/rules/iofstreammissingpositioning/test.c new file mode 100644 index 0000000000..09a6b1657a --- /dev/null +++ b/c/common/test/rules/iofstreammissingpositioning/test.c @@ -0,0 +1,63 @@ +#include + +enum { BUFFERSIZE = 32 }; + +extern void initialize_data(char *data, size_t size); + +void f1(const char *file_name) { + char data[BUFFERSIZE]; + char append_data[BUFFERSIZE]; + FILE *file; + + file = fopen(file_name, "a+"); + + if (fwrite(append_data, 1, BUFFERSIZE, file) != BUFFERSIZE) { + } + if (fread(data, 1, BUFFERSIZE, file) < BUFFERSIZE) { // NON_COMPLIANT + } + + if (fclose(file) == EOF) { + } +} + +FILE *global_file; +void f2(const char *file_name) { + char data[BUFFERSIZE]; + char append_data[BUFFERSIZE]; + + global_file = fopen(file_name, "a+"); + + if (fwrite(append_data, 1, BUFFERSIZE, global_file) != BUFFERSIZE) { + } + if (fread(data, 1, BUFFERSIZE, global_file) < BUFFERSIZE) { // NON_COMPLIANT + } + + if (fclose(global_file) == EOF) { + } +} + +void f3(const char *file_name) { + char data[BUFFERSIZE]; + char append_data[BUFFERSIZE]; + FILE *file = fopen(file_name, "a+"); + if (file == NULL) { + /* Handle error */ + } + + initialize_data(append_data, BUFFERSIZE); + if (fwrite(append_data, BUFFERSIZE, 1, file) != BUFFERSIZE) { + /* Handle error */ + } + + if (fseek(file, 0L, SEEK_SET) != 0) { + /* Handle error */ + } + + if (fread(data, BUFFERSIZE, 1, file) != 0) { // COMPLIANT + /* Handle there not being data */ + } + + if (fclose(file) == EOF) { + /* Handle error */ + } +} diff --git a/c/common/test/rules/nonconstantformat/NonConstantFormat.expected b/c/common/test/rules/nonconstantformat/NonConstantFormat.expected new file mode 100644 index 0000000000..3f04d02716 --- /dev/null +++ b/c/common/test/rules/nonconstantformat/NonConstantFormat.expected @@ -0,0 +1,2 @@ +| test.c:12:19:12:21 | msg | The format string argument to `$@` should be constant to prevent security issues and other potential errors. | test.c:12:3:12:9 | call to fprintf | fprintf | +| test.c:38:20:38:22 | msg | The format string argument to `$@` should be constant to prevent security issues and other potential errors. | test.c:38:3:38:8 | call to syslog | syslog | diff --git a/c/common/test/rules/nonconstantformat/NonConstantFormat.ql b/c/common/test/rules/nonconstantformat/NonConstantFormat.ql new file mode 100644 index 0000000000..7a92b544e2 --- /dev/null +++ b/c/common/test/rules/nonconstantformat/NonConstantFormat.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.nonconstantformat.NonConstantFormat diff --git a/c/common/test/rules/nonconstantformat/test.c b/c/common/test/rules/nonconstantformat/test.c new file mode 100644 index 0000000000..ad5a4fb8f4 --- /dev/null +++ b/c/common/test/rules/nonconstantformat/test.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +void f1(const char *user) { + int ret; + static const char msg_format[] = "Hello %s."; + size_t len = strlen(user) + sizeof(msg_format); + char *msg = (char *)malloc(len); + ret = snprintf(msg, len, msg_format, user); + fprintf(stderr, msg); // NON_COMPLIANT + free(msg); +} + +void f2(const char *user) { + int ret; + static const char msg_format[] = "Hello %s."; + size_t len = strlen(user) + sizeof(msg_format); + char *msg = (char *)malloc(len); + ret = snprintf(msg, len, msg_format, user); + fputs(msg, stderr); // COMPLIANT + free(msg); +} + +void f3(const char *user) { + static const char msg_format[] = "Hello %s."; + fprintf(stderr, msg_format, user); // COMPLIANT +} + +// POSIX // +void f4(const char *user) { + int ret; + static const char msg_format[] = "Hello %s."; + size_t len = strlen(user) + sizeof(msg_format); + char *msg = (char *)malloc(len); + ret = snprintf(msg, len, msg_format, user); + syslog(LOG_INFO, msg); // NON_COMPLIANT + free(msg); +} + +void f5(const char *user) { + static const char msg_format[] = "Hello %s."; + syslog(LOG_INFO, msg_format, user); // COMPLIANT +} diff --git a/c/common/test/rules/preprocessorincludesforbiddenheadernames/'badheader.h b/c/common/test/rules/preprocessorincludesforbiddenheadernames/'badheader.h new file mode 100644 index 0000000000..fc0512b28e --- /dev/null +++ b/c/common/test/rules/preprocessorincludesforbiddenheadernames/'badheader.h @@ -0,0 +1 @@ +int j = 0; \ No newline at end of file diff --git a/c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.expected b/c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.expected new file mode 100644 index 0000000000..5eac7bea89 --- /dev/null +++ b/c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.expected @@ -0,0 +1,2 @@ +| test.c:4:1:4:23 | #include "'badheader.h" | The #include of "'badheader.h" contains a character sequence with implementation-defined behavior. | +| test.c:5:1:5:23 | #include "badheade'r.h" | The #include of "badheade'r.h" contains a character sequence with implementation-defined behavior. | diff --git a/c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql b/c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql new file mode 100644 index 0000000000..1b27d1e0ee --- /dev/null +++ b/c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.preprocessorincludesforbiddenheadernames.PreprocessorIncludesForbiddenHeaderNames diff --git a/c/common/test/rules/preprocessorincludesforbiddenheadernames/badheade'r.h b/c/common/test/rules/preprocessorincludesforbiddenheadernames/badheade'r.h new file mode 100644 index 0000000000..5a00775c4a --- /dev/null +++ b/c/common/test/rules/preprocessorincludesforbiddenheadernames/badheade'r.h @@ -0,0 +1 @@ +int i = 0; \ No newline at end of file diff --git a/cpp/autosar/test/rules/A16-2-1/test.cpp b/c/common/test/rules/preprocessorincludesforbiddenheadernames/test.c similarity index 100% rename from cpp/autosar/test/rules/A16-2-1/test.cpp rename to c/common/test/rules/preprocessorincludesforbiddenheadernames/test.c diff --git a/c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.expected b/c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.expected new file mode 100644 index 0000000000..5b0973906e --- /dev/null +++ b/c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.expected @@ -0,0 +1 @@ +| test.c:4:1:4:18 | #include "test1.h" | #include "test1.h" is preceded by a non-preprocessor or comment code element. | diff --git a/c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql b/c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql new file mode 100644 index 0000000000..343b168637 --- /dev/null +++ b/c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.preprocessorincludespreceded.PreprocessorIncludesPreceded diff --git a/c/common/test/rules/preprocessorincludespreceded/test.c b/c/common/test/rules/preprocessorincludespreceded/test.c new file mode 100644 index 0000000000..374b02cbf5 --- /dev/null +++ b/c/common/test/rules/preprocessorincludespreceded/test.c @@ -0,0 +1,4 @@ +#include "test.h" //COMPLIANT + +int x = 0; +#include "test1.h" //NON_COMPLIANT \ No newline at end of file diff --git a/c/common/test/rules/preprocessorincludespreceded/test.h b/c/common/test/rules/preprocessorincludespreceded/test.h new file mode 100644 index 0000000000..1bd2b2e187 --- /dev/null +++ b/c/common/test/rules/preprocessorincludespreceded/test.h @@ -0,0 +1 @@ +int i = 0; diff --git a/c/common/test/rules/preprocessorincludespreceded/test1.h b/c/common/test/rules/preprocessorincludespreceded/test1.h new file mode 100644 index 0000000000..9b0b503749 --- /dev/null +++ b/c/common/test/rules/preprocessorincludespreceded/test1.h @@ -0,0 +1 @@ +int j = 0; diff --git a/c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.expected b/c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.expected new file mode 100644 index 0000000000..cc9acfb4c7 --- /dev/null +++ b/c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.expected @@ -0,0 +1,4 @@ +| test.c:3:1:3:10 | #if NOTDEF | #if/#elif that uses a macro identifier NOTDEF that may be undefined. | +| test.c:19:1:19:31 | #if defined(MACROONE) \|\| NOTDEF | #if/#elif that uses a macro identifier NOTDEF that may be undefined. | +| test.c:22:1:22:31 | #if defined(MACROONE) && NOTDEF | #if/#elif that uses a macro identifier NOTDEF that may be undefined. | +| test.c:31:1:31:12 | #if MACROTWO | #if/#elif that uses a macro identifier MACROTWO that may be undefined. | diff --git a/c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql b/c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql new file mode 100644 index 0000000000..afede1b8ef --- /dev/null +++ b/c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.undefinedmacroidentifiers.UndefinedMacroIdentifiers diff --git a/c/common/test/rules/undefinedmacroidentifiers/test.c b/c/common/test/rules/undefinedmacroidentifiers/test.c new file mode 100644 index 0000000000..7d3d18577a --- /dev/null +++ b/c/common/test/rules/undefinedmacroidentifiers/test.c @@ -0,0 +1,44 @@ +#define MACROONE 0 + +#if NOTDEF // NON_COMPLIANT +#endif + +#if MACROONE // COMPLIANT +#elif MACROONE // COMPLIANT +#endif + +#if defined(MACROONE) // COMPLIANT +#endif + +#if defined NOTDEF // COMPLIANT +#endif + +#if defined(MACROONE) // COMPLIANT +#endif + +#if defined(MACROONE) || NOTDEF // NON_COMPLIANT +#endif + +#if defined(MACROONE) && NOTDEF // COMPLIANT[FALSE_POSITIVE] +#endif + +#define MACROTWO 0 + +#if MACROTWO // COMPLIANT +#endif +#undef MACROTWO + +#if MACROTWO // NON_COMPLIANT +#endif + +#define MACROTWO 0 +#if MACROTWO // COMPLIANT +#endif + +#if 1 + 1 > 3 // COMPLIANT +#endif + +#if defined MACROTHREE && (defined(MACROONE)) +#if MACROONE // COMPLIANT +#endif +#endif \ No newline at end of file diff --git a/c/misra/src/codeql-suites/misra-default.qls b/c/misra/src/codeql-suites/misra-default.qls new file mode 100644 index 0000000000..d32637556d --- /dev/null +++ b/c/misra/src/codeql-suites/misra-default.qls @@ -0,0 +1,10 @@ +- description: MISRA C 2012 (Default) +- qlpack: misra-c-coding-standards +- include: + kind: + - problem + - path-problem +- exclude: + tags contain: + - external/misra/audit + - external/misra/default-disabled \ No newline at end of file diff --git a/c/misra/src/codingstandards/c/misra.qll b/c/misra/src/codingstandards/c/misra.qll new file mode 100644 index 0000000000..728334e5d6 --- /dev/null +++ b/c/misra/src/codingstandards/c/misra.qll @@ -0,0 +1,4 @@ +import cpp +import misra.Customizations +import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.c.RuleMetadata diff --git a/c/misra/src/codingstandards/c/misra/Customizations.qll b/c/misra/src/codingstandards/c/misra/Customizations.qll new file mode 100644 index 0000000000..4996ace845 --- /dev/null +++ b/c/misra/src/codingstandards/c/misra/Customizations.qll @@ -0,0 +1 @@ +import cpp diff --git a/c/misra/src/qlpack.yml b/c/misra/src/qlpack.yml new file mode 100644 index 0000000000..ac60340e88 --- /dev/null +++ b/c/misra/src/qlpack.yml @@ -0,0 +1,4 @@ +name: misra-c-coding-standards +version: 2.0.0 +suites: codeql-suites +libraryPathDependencies: common-c-coding-standards diff --git a/c/misra/src/rules/RULE-20-1/IncludeDirectivesPrecededByDirectivesOrComments.ql b/c/misra/src/rules/RULE-20-1/IncludeDirectivesPrecededByDirectivesOrComments.ql new file mode 100644 index 0000000000..aa0d733eb2 --- /dev/null +++ b/c/misra/src/rules/RULE-20-1/IncludeDirectivesPrecededByDirectivesOrComments.ql @@ -0,0 +1,22 @@ +/** + * @id c/misra/include-directives-preceded-by-directives-or-comments + * @name RULE-20-1: #include directives should only be preceded by preprocessor directives or comments + * @description Using anything other than other pre-processor directives or comments before an + * '#include' directive makes the code more difficult to read. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-20-1 + * readability + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.preprocessorincludespreceded.PreprocessorIncludesPreceded + +class PreprocessorIncludesPrecededQuery extends PreprocessorIncludesPrecededSharedQuery { + PreprocessorIncludesPrecededQuery() { + this = Preprocessor1Package::includeDirectivesPrecededByDirectivesOrCommentsQuery() + } +} diff --git a/c/misra/src/rules/RULE-20-10/PreprocessorHashOperatorsShouldNotBeUsed.ql b/c/misra/src/rules/RULE-20-10/PreprocessorHashOperatorsShouldNotBeUsed.ql new file mode 100644 index 0000000000..3d6b30f875 --- /dev/null +++ b/c/misra/src/rules/RULE-20-10/PreprocessorHashOperatorsShouldNotBeUsed.ql @@ -0,0 +1,22 @@ +/** + * @id c/misra/preprocessor-hash-operators-should-not-be-used + * @name RULE-20-10: The # and ## preprocessor operators should not be used + * @description The order of evaluation for the '#' and '##' operators may differ between compilers, + * which can cause unexpected behaviour. + * @kind problem + * @precision very-high + * @problem.severity warning + * @tags external/misra/id/rule-20-10 + * correctness + * external/misra/obligation/advisory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.hashoperatorsused.HashOperatorsUsed + +class HashOperatorsUsedInQuery extends HashOperatorsUsedQuery { + HashOperatorsUsedInQuery() { + this = Preprocessor1Package::preprocessorHashOperatorsShouldNotBeUsedQuery() + } +} diff --git a/c/misra/src/rules/RULE-20-2/ForbiddenCharactersInHeaderFileName.ql b/c/misra/src/rules/RULE-20-2/ForbiddenCharactersInHeaderFileName.ql new file mode 100644 index 0000000000..9ef3c76c49 --- /dev/null +++ b/c/misra/src/rules/RULE-20-2/ForbiddenCharactersInHeaderFileName.ql @@ -0,0 +1,22 @@ +/** + * @id c/misra/forbidden-characters-in-header-file-name + * @name RULE-20-2: The ', " or \ characters and the /* or // character sequences shall not occur in a header file name + * @description Using any of the following characters in an '#include' directive as a part of the + * header file name is undefined behaviour: ', ", /*, //, \. + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-20-2 + * correctness + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.preprocessorincludesforbiddenheadernames.PreprocessorIncludesForbiddenHeaderNames + +class PreprocessorIncludesForbiddenHeaderNames extends PreprocessorIncludesForbiddenHeaderNamesQuery { + PreprocessorIncludesForbiddenHeaderNames() { + this = Preprocessor1Package::forbiddenCharactersInHeaderFileNameQuery() + } +} diff --git a/c/misra/src/rules/RULE-20-9/IdentifiersUsedInPreprocessorExpression.ql b/c/misra/src/rules/RULE-20-9/IdentifiersUsedInPreprocessorExpression.ql new file mode 100644 index 0000000000..df01ec00e4 --- /dev/null +++ b/c/misra/src/rules/RULE-20-9/IdentifiersUsedInPreprocessorExpression.ql @@ -0,0 +1,24 @@ +/** + * @id c/misra/identifiers-used-in-preprocessor-expression + * @name RULE-20-9: All identifiers used in the controlling expression of #if or #elif preprocessing directives shall be + * @description Using undefined macro identifiers in #if or #elif pre-processor directives, except + * as operands to the defined operator, can cause the code to be hard to understand + * because the preprocessor will just treat the value as 0 and no warning is given. + * @kind problem + * @precision high + * @problem.severity warning + * @tags external/misra/id/rule-20-9 + * correctness + * readability + * external/misra/obligation/required + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.undefinedmacroidentifiers.UndefinedMacroIdentifiers + +class UndefinedMacroIdentifiersUsedInQuery extends UndefinedMacroIdentifiersQuery { + UndefinedMacroIdentifiersUsedInQuery() { + this = Preprocessor1Package::identifiersUsedInPreprocessorExpressionQuery() + } +} diff --git a/c/misra/src/rules/RULE-22-6/FileUsedAfterClosed.ql b/c/misra/src/rules/RULE-22-6/FileUsedAfterClosed.ql new file mode 100644 index 0000000000..3a4be49925 --- /dev/null +++ b/c/misra/src/rules/RULE-22-6/FileUsedAfterClosed.ql @@ -0,0 +1,19 @@ +/** + * @id c/misra/file-used-after-closed + * @name RULE-22-6: The value of a pointer to a FILE shall not be used after the associated stream has been closed + * @description A closed FILE is accessed + * @kind problem + * @precision very-high + * @problem.severity error + * @tags external/misra/id/rule-22-6 + * correctness + * external/misra/obligation/mandatory + */ + +import cpp +import codingstandards.c.misra +import codingstandards.cpp.rules.donotaccessaclosedfile.DoNotAccessAClosedFile + +class FileUsedAfterClosedQuery extends DoNotAccessAClosedFileSharedQuery { + FileUsedAfterClosedQuery() { this = IO1Package::fileUsedAfterClosedQuery() } +} diff --git a/c/misra/src/rules/RULE-22-6/standard-example.c b/c/misra/src/rules/RULE-22-6/standard-example.c new file mode 100644 index 0000000000..8c3766ac9c --- /dev/null +++ b/c/misra/src/rules/RULE-22-6/standard-example.c @@ -0,0 +1,15 @@ +#include + +void fn(void) { + FILE *fp; + FILE *p; + + fp = fopen("tmp", "w"); + if (fp == NULL) { + error_action(); + } + fclose(fp); + + fprintf(fp, "?"); /* Non-compliant */ + p = fp; /* Non-compliant */ +} \ No newline at end of file diff --git a/c/misra/test/qlpack.yml b/c/misra/test/qlpack.yml new file mode 100644 index 0000000000..66838930da --- /dev/null +++ b/c/misra/test/qlpack.yml @@ -0,0 +1,4 @@ +name: misra-c-coding-standards-tests +version: 2.0.0 +libraryPathDependencies: misra-c-coding-standards +extractor: cpp \ No newline at end of file diff --git a/c/misra/test/rules/RULE-20-1/IncludeDirectivesPrecededByDirectivesOrComments.testref b/c/misra/test/rules/RULE-20-1/IncludeDirectivesPrecededByDirectivesOrComments.testref new file mode 100644 index 0000000000..e20bf14e19 --- /dev/null +++ b/c/misra/test/rules/RULE-20-1/IncludeDirectivesPrecededByDirectivesOrComments.testref @@ -0,0 +1 @@ +c/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-20-10/PreprocessorHashOperatorsShouldNotBeUsed.testref b/c/misra/test/rules/RULE-20-10/PreprocessorHashOperatorsShouldNotBeUsed.testref new file mode 100644 index 0000000000..249fb829ae --- /dev/null +++ b/c/misra/test/rules/RULE-20-10/PreprocessorHashOperatorsShouldNotBeUsed.testref @@ -0,0 +1 @@ +c/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-20-2/ForbiddenCharactersInHeaderFileName.testref b/c/misra/test/rules/RULE-20-2/ForbiddenCharactersInHeaderFileName.testref new file mode 100644 index 0000000000..dbd11989f6 --- /dev/null +++ b/c/misra/test/rules/RULE-20-2/ForbiddenCharactersInHeaderFileName.testref @@ -0,0 +1 @@ +c/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-20-9/IdentifiersUsedInPreprocessorExpression.testref b/c/misra/test/rules/RULE-20-9/IdentifiersUsedInPreprocessorExpression.testref new file mode 100644 index 0000000000..326117cd0a --- /dev/null +++ b/c/misra/test/rules/RULE-20-9/IdentifiersUsedInPreprocessorExpression.testref @@ -0,0 +1 @@ +c/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql \ No newline at end of file diff --git a/c/misra/test/rules/RULE-22-6/FileUsedAfterClosed.testref b/c/misra/test/rules/RULE-22-6/FileUsedAfterClosed.testref new file mode 100644 index 0000000000..02420f16e4 --- /dev/null +++ b/c/misra/test/rules/RULE-22-6/FileUsedAfterClosed.testref @@ -0,0 +1 @@ +c/common/test/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.ql \ No newline at end of file diff --git a/c/options b/c/options new file mode 100644 index 0000000000..367678d1cf --- /dev/null +++ b/c/options @@ -0,0 +1 @@ +semmle-extractor-options:--clangg -std=c99 --edg --diag_error=implicit_func_decl -nostdinc -I../../../../common/test/includes/standard-library \ No newline at end of file diff --git a/change_notes/2021-10-26-enable-lifetime-profile.md b/change_notes/2021-10-26-enable-lifetime-profile.md deleted file mode 100644 index 11c3bb3b90..0000000000 --- a/change_notes/2021-10-26-enable-lifetime-profile.md +++ /dev/null @@ -1,2 +0,0 @@ - - `A3-8-1`, `A5-3-2`, `EXP54-CPP`, `STR51-CPP` - - All queries for these rules are now enabled by default. They previously disabled due to performance concerns. diff --git a/change_notes/2022-03-04-address-fp-m7-3-4.md b/change_notes/2022-03-04-address-fp-m7-3-4.md deleted file mode 100644 index 5339f0b950..0000000000 --- a/change_notes/2022-03-04-address-fp-m7-3-4.md +++ /dev/null @@ -1 +0,0 @@ -- Address a false positive flagged by `cpp/autosar/using-directives-used` for anonymous namespaces. \ No newline at end of file diff --git a/change_notes/2022-03-16-fix-placeholders.md b/change_notes/2022-03-16-fix-placeholders.md deleted file mode 100644 index 9ba3f1856a..0000000000 --- a/change_notes/2022-03-16-fix-placeholders.md +++ /dev/null @@ -1,4 +0,0 @@ -- `A10-2-1` - `NonVirtualPublicOrProtectedFunctionsRedefinedQuery`: - - Fixed a typo that caused the derived class not to be displayed in the alert message -- `A10-3-3` - `VirtualFunctionsIntroducedInFinalClassQuery` - - Fixed a typo that caused the introducing class not to be displayed in the alert message diff --git a/change_notes/2022-03-18 b/change_notes/2022-03-18 deleted file mode 100644 index f458830472..0000000000 --- a/change_notes/2022-03-18 +++ /dev/null @@ -1 +0,0 @@ -- Update the `create_release.sh` script to include query artifacts with Markdown help files diff --git a/change_notes/2022-03-18-address-fp-A3-3-1.md b/change_notes/2022-03-18-address-fp-A3-3-1.md deleted file mode 100644 index 03c6f2cf02..0000000000 --- a/change_notes/2022-03-18-address-fp-A3-3-1.md +++ /dev/null @@ -1 +0,0 @@ -- Address a false positive flagged by `cpp/autosar/external-linkage-not-declared-in-header-file` for declarations that actually were in header files \ No newline at end of file diff --git a/change_notes/2022-03-24-update-release-artifacts.md b/change_notes/2022-03-24-update-release-artifacts.md deleted file mode 100644 index 91d53a95bb..0000000000 --- a/change_notes/2022-03-24-update-release-artifacts.md +++ /dev/null @@ -1 +0,0 @@ -- Updated release artifacts naming convention to include the explicit tag in the filename and updated the user manual. \ No newline at end of file diff --git a/codeql_modules/codeql b/codeql_modules/codeql index a1cdf256ad..06b36f742e 160000 --- a/codeql_modules/codeql +++ b/codeql_modules/codeql @@ -1 +1 @@ -Subproject commit a1cdf256ad6b7c3e9984db9069671647e5f47921 +Subproject commit 06b36f742e88b610e0c2b75e2668603fc3a0f359 diff --git a/cpp/autosar/src/codingstandards/cpp/autosar.qll b/cpp/autosar/src/codingstandards/cpp/autosar.qll index fd42ca3f53..6d4ac487a4 100644 --- a/cpp/autosar/src/codingstandards/cpp/autosar.qll +++ b/cpp/autosar/src/codingstandards/cpp/autosar.qll @@ -1,3 +1,4 @@ import cpp import autosar.Customizations import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.cpp.RuleMetadata diff --git a/cpp/autosar/src/qlpack.yml b/cpp/autosar/src/qlpack.yml index d3c01e7485..cdc63a6ec0 100644 --- a/cpp/autosar/src/qlpack.yml +++ b/cpp/autosar/src/qlpack.yml @@ -1,4 +1,4 @@ name: autosar-cpp-coding-standards -version: 1.1.0 +version: 2.0.0 suites: codeql-suites libraryPathDependencies: common-cpp-coding-standards diff --git a/cpp/autosar/src/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.ql b/cpp/autosar/src/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.ql index 8a377b9f65..ef14664bf9 100644 --- a/cpp/autosar/src/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.ql +++ b/cpp/autosar/src/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.ql @@ -44,5 +44,5 @@ where subclass = shadowingVariable.getDeclaringType() ) ) -select f, "Member function $@ is shadowed by $@ in derived class $@", f, f.getName(), e, +select f, "Member function $@ is shadowed by $@ in derived class @a", f, f.getName(), e, description, subclass, subclass.getName() diff --git a/cpp/autosar/src/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.ql b/cpp/autosar/src/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.ql index 2085be5b99..4e9d5c3131 100644 --- a/cpp/autosar/src/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.ql +++ b/cpp/autosar/src/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.ql @@ -27,5 +27,5 @@ where not f.isDefaulted() and not f.isCompilerGenerated() and not f.getBlock().getLocation().hasLocationInfo("", 0, 0, 0, 0) -select f, "Non-final virtual function $@ is introduced in final class $@.", f, f.getName(), +select f, "Non-final virtual function $@ is introduced in final class @$.", f, f.getName(), f.getDeclaringType(), f.getDeclaringType().getName() diff --git a/cpp/autosar/src/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.ql b/cpp/autosar/src/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.ql index e210988614..9892f49b00 100644 --- a/cpp/autosar/src/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.ql +++ b/cpp/autosar/src/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.ql @@ -15,15 +15,10 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.rules.preprocessorincludesforbiddenheadernames.PreprocessorIncludesForbiddenHeaderNames -class InvalidInclude extends Include { - InvalidInclude() { this.getIncludeText().regexpMatch("[\"<].*(['\"\\\\]|\\/\\*|\\/\\/).*[\">]") } +class CharactersOccurInHeaderFileNameOrInIncludeDirectiveQuery extends PreprocessorIncludesForbiddenHeaderNamesQuery { + CharactersOccurInHeaderFileNameOrInIncludeDirectiveQuery() { + this = MacrosPackage::charactersOccurInHeaderFileNameOrInIncludeDirectiveQuery() + } } - -from Include i -where - not isExcluded(i, MacrosPackage::charactersOccurInHeaderFileNameOrInIncludeDirectiveQuery()) and - i instanceof InvalidInclude -select i, - "The #include of " + i.getIncludeText() + - " contains a character sequence with implementation-defined behavior." diff --git a/cpp/autosar/src/rules/A23-0-2/ValidContainerElementAccess.ql b/cpp/autosar/src/rules/A23-0-2/ValidContainerElementAccess.ql index 9b114c5d7b..f801574088 100644 --- a/cpp/autosar/src/rules/A23-0-2/ValidContainerElementAccess.ql +++ b/cpp/autosar/src/rules/A23-0-2/ValidContainerElementAccess.ql @@ -18,7 +18,5 @@ import codingstandards.cpp.autosar import codingstandards.cpp.rules.validcontainerelementaccess.ValidContainerElementAccess class ValidContainerElementAccessQuery extends ValidContainerElementAccessSharedQuery { - ValidContainerElementAccessQuery() { - this = IteratorsPackage::validContainerElementAccessQuery() - } + ValidContainerElementAccessQuery() { this = IteratorsPackage::validContainerElementAccessQuery() } } diff --git a/cpp/autosar/src/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.ql b/cpp/autosar/src/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.ql index 0b71952eba..53c058a16c 100644 --- a/cpp/autosar/src/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.ql +++ b/cpp/autosar/src/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.ql @@ -13,131 +13,12 @@ * external/autosar/obligation/required */ +import cpp import codingstandards.cpp.autosar -import semmle.code.cpp.dataflow.TaintTracking -import semmle.code.cpp.commons.Printf +import codingstandards.cpp.rules.nonconstantformat.NonConstantFormat -// For the following `...gettext` functions, we assume that -// all translations preserve the type and order of `%` specifiers -// (and hence are safe to use as format strings). This -// assumption is hard-coded into the query. -predicate whitelistFunction(Function f, int arg) { - // basic variations of gettext - f.getName() = "_" and arg = 0 - or - f.getName() = "gettext" and arg = 0 - or - f.getName() = "dgettext" and arg = 1 - or - f.getName() = "dcgettext" and arg = 1 - or - // plural variations of gettext that take one format string for singular and another for plural form - f.getName() = "ngettext" and - (arg = 0 or arg = 1) - or - f.getName() = "dngettext" and - (arg = 1 or arg = 2) - or - f.getName() = "dcngettext" and - (arg = 1 or arg = 2) -} - -// we assume that ALL uses of the `_` macro -// return constant string literals -predicate underscoreMacro(Expr e) { - exists(MacroInvocation mi | - mi.getMacroName() = "_" and - mi.getExpr() = e - ) -} - -/** - * Holds if `t` cannot hold a character array, directly or indirectly. - */ -predicate cannotContainString(Type t) { - t.getUnspecifiedType() instanceof BuiltInType - or - t.getUnspecifiedType() instanceof IntegralOrEnumType -} - -predicate isNonConst(DataFlow::Node node) { - exists(Expr e | e = node.asExpr() | - exists(FunctionCall fc | fc = e.(FunctionCall) | - not ( - whitelistFunction(fc.getTarget(), _) or - fc.getTarget().hasDefinition() - ) - ) - or - exists(Parameter p | p = e.(VariableAccess).getTarget().(Parameter) | - p.getFunction().getName() = "main" and p.getType() instanceof PointerType - ) - or - e instanceof CrementOperation - or - e instanceof AddressOfExpr - or - e instanceof ReferenceToExpr - or - e instanceof AssignPointerAddExpr - or - e instanceof AssignPointerSubExpr - or - e instanceof PointerArithmeticOperation - or - e instanceof FieldAccess - or - e instanceof PointerDereferenceExpr - or - e instanceof AddressOfExpr - or - e instanceof ExprCall - or - e instanceof NewArrayExpr - or - e instanceof AssignExpr - or - exists(Variable v | v = e.(VariableAccess).getTarget() | - v.getType().(ArrayType).getBaseType() instanceof CharType and - exists(AssignExpr ae | - ae.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = v - ) - ) - ) - or - node instanceof DataFlow::DefinitionByReferenceNode -} - -pragma[noinline] -predicate isSanitizerNode(DataFlow::Node node) { - underscoreMacro(node.asExpr()) - or - cannotContainString(node.getType()) -} - -class NonConstFlow extends TaintTracking::Configuration { - NonConstFlow() { this = "NonConstFlow" } - - override predicate isSource(DataFlow::Node source) { - isNonConst(source) and - not cannotContainString(source.getType()) +class InputsFromIndependentComponentsNotValidatedQuery extends NonConstantFormatSharedQuery { + InputsFromIndependentComponentsNotValidatedQuery() { + this = TypeRangesPackage::inputsFromIndependentComponentsNotValidatedQuery() } - - override predicate isSink(DataFlow::Node sink) { - exists(FormattingFunctionCall fc | sink.asExpr() = fc.getArgument(fc.getFormatParameterIndex())) - } - - override predicate isSanitizer(DataFlow::Node node) { isSanitizerNode(node) } } - -from FormattingFunctionCall call, Expr formatString -where - not isExcluded(formatString, TypeRangesPackage::inputsFromIndependentComponentsNotValidatedQuery()) and - call.getArgument(call.getFormatParameterIndex()) = formatString and - exists(NonConstFlow cf, DataFlow::Node source, DataFlow::Node sink | - cf.hasFlow(source, sink) and - sink.asExpr() = formatString - ) -select formatString, - "The format string argument to `" + call.getTarget().getName() + - "` should be constant to prevent security issues and other potential errors." diff --git a/cpp/autosar/src/rules/A3-3-1/ExternalLinkageNotDeclaredInHeaderFile.ql b/cpp/autosar/src/rules/A3-3-1/ExternalLinkageNotDeclaredInHeaderFile.ql index e7bff9ef71..ec24bb2696 100644 --- a/cpp/autosar/src/rules/A3-3-1/ExternalLinkageNotDeclaredInHeaderFile.ql +++ b/cpp/autosar/src/rules/A3-3-1/ExternalLinkageNotDeclaredInHeaderFile.ql @@ -29,9 +29,7 @@ where // The declaration with external linkage does not have a declaration in a header file exists(Compilation c | de.getFile() = c.getAFileCompiled()) and not exists(DeclarationEntry otherDe | - de.getDeclaration() = otherDe.getDeclaration() and - not de = otherDe and - not otherDe.isDefinition() + de.getDeclaration() = otherDe.getDeclaration() and not de = otherDe and not de.isDefinition() | otherDe.getFile() instanceof HeaderFile ) and diff --git a/cpp/autosar/src/rules/A3-8-1/ObjectAccessedAfterLifetimeAutosar.ql b/cpp/autosar/src/rules/A3-8-1/ObjectAccessedAfterLifetimeAutosar.ql index 7db181c513..6ba2f286bb 100644 --- a/cpp/autosar/src/rules/A3-8-1/ObjectAccessedAfterLifetimeAutosar.ql +++ b/cpp/autosar/src/rules/A3-8-1/ObjectAccessedAfterLifetimeAutosar.ql @@ -8,6 +8,7 @@ * @tags external/autosar/id/a3-8-1 * correctness * security + * external/autosar/default-disabled * external/autosar/allocated-target/implementation * external/autosar/enforcement/non-automated * external/autosar/obligation/required diff --git a/cpp/autosar/src/rules/A3-8-1/ObjectAccessedBeforeLifetimeAutosar.ql b/cpp/autosar/src/rules/A3-8-1/ObjectAccessedBeforeLifetimeAutosar.ql index 3f63ef4cb0..a6c58f4106 100644 --- a/cpp/autosar/src/rules/A3-8-1/ObjectAccessedBeforeLifetimeAutosar.ql +++ b/cpp/autosar/src/rules/A3-8-1/ObjectAccessedBeforeLifetimeAutosar.ql @@ -8,6 +8,7 @@ * @tags external/autosar/id/a3-8-1 * correctness * security + * external/autosar/default-disabled * external/autosar/allocated-target/implementation * external/autosar/enforcement/non-automated * external/autosar/obligation/required diff --git a/cpp/autosar/src/rules/A5-3-2/NullPointersDereferenced.ql b/cpp/autosar/src/rules/A5-3-2/NullPointersDereferenced.ql index 5ee527943b..0b637448ad 100644 --- a/cpp/autosar/src/rules/A5-3-2/NullPointersDereferenced.ql +++ b/cpp/autosar/src/rules/A5-3-2/NullPointersDereferenced.ql @@ -7,6 +7,7 @@ * @problem.severity error * @tags external/autosar/id/a5-3-2 * correctness + * external/autosar/default-disabled * external/autosar/allocated-target/implementation * external/autosar/enforcement/partially-automated * external/autosar/obligation/required diff --git a/cpp/autosar/src/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.ql b/cpp/autosar/src/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.ql index a6a270695b..89d0b3a4bc 100644 --- a/cpp/autosar/src/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.ql +++ b/cpp/autosar/src/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.ql @@ -15,36 +15,10 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.rules.preprocessorincludespreceded.PreprocessorIncludesPreceded -class PreprocessorBranchMacroAccess extends MacroAccess { - PreprocessorBranchMacroAccess() { - // We're only interested in cases in the users source code - exists(getFile().getRelativePath()) and - exists(PreprocessorBranchDirective pd, string filepath, int startline | - pd.getLocation().hasLocationInfo(filepath, startline, _, _, _) and - getLocation().hasLocationInfo(filepath, startline, _, _, _) - ) +class PreprocessorIncludesPrecededQuery extends PreprocessorIncludesPrecededSharedQuery { + PreprocessorIncludesPrecededQuery() { + this = MacrosPackage::includeDirectivesNotPrecededByDirectivesOrCommentsQuery() } } - -class NotIncludeOrCommentElement extends Element { - NotIncludeOrCommentElement() { - exists(getFile().getRelativePath()) and - not ( - this instanceof PreprocessorDirective or - this instanceof Comment or - this instanceof File or - this instanceof PreprocessorBranchMacroAccess - ) - } -} - -from NotIncludeOrCommentElement first, Include second -where - exists(string filepath, int firststartline, int secondstartline | - first.getLocation().hasLocationInfo(filepath, firststartline, _, _, _) and - second.getLocation().hasLocationInfo(filepath, secondstartline, _, _, _) and - firststartline < secondstartline - ) and - not isExcluded(second, MacrosPackage::includeDirectivesNotPrecededByDirectivesOrCommentsQuery()) -select second, second + " is preceded by a non-preprocessor or comment code element." diff --git a/cpp/autosar/src/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.ql b/cpp/autosar/src/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.ql index 66fc9ed276..9e0ceb1051 100644 --- a/cpp/autosar/src/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.ql +++ b/cpp/autosar/src/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.ql @@ -17,117 +17,10 @@ import cpp import codingstandards.cpp.autosar +import codingstandards.cpp.rules.undefinedmacroidentifiers.UndefinedMacroIdentifiers -pragma[noinline] -predicate isMacroAccessFileAndLine(MacroAccess ma, string filepath, int startLine) { - ma.getLocation().hasLocationInfo(filepath, startLine, _, _, _) -} - -pragma[noinline] -predicate isPreprocFileAndLine(PreprocessorBranchDirective pd, string filepath, int startLine) { - pd.getLocation().hasLocationInfo(filepath, startLine, _, _, _) -} - -/** - * A `MacroAccess` that occurs in a `PreprocessorBranchDirective`. - * - * Example: - * ``` - * #if FOO_BAR != 30 - * ... - * ``` - */ -class PreprocessorBranchMacroAccess extends MacroAccess { - PreprocessorBranch pd; - - PreprocessorBranchMacroAccess() { - // We're only interested in cases in the users source code - exists(getFile().getRelativePath()) and - // There must a be a `PreprocessorBranch` that occurs in the same file, and on the - // same line - exists(string filepath, int startLine | - // Extracted to improve join order - isPreprocFileAndLine(pd, filepath, startLine) and - isMacroAccessFileAndLine(this, filepath, startLine) - ) +class UndefinedMacroIdentifiersUsedInQuery extends UndefinedMacroIdentifiersQuery { + UndefinedMacroIdentifiersUsedInQuery() { + this = MacrosPackage::charactersOccurInHeaderFileNameOrInIncludeDirectiveQuery() } - - PreprocessorBranch getBranchDirective() { result = pd } -} - -/** - * An optimised version of `PreprocessorBranchDirective.getAGuard()`. - */ -private PreprocessorBranch getAGuard(PreprocessorBranch pb) { - exists( - PreprocessorEndif end, string filepath, int guardStartLine, int pbStartLine, int endifStartLine - | - result.getEndIf() = end - | - isPreprocFileAndLine(result, filepath, guardStartLine) and - isPreprocFileAndLine(pb, filepath, pbStartLine) and - isPreprocFileAndLine(end, filepath, endifStartLine) and - guardStartLine < pbStartLine and - pbStartLine < endifStartLine - ) } - -/** Gets a macro identifier which is #ifdef checked in `pb`. */ -string getAnIfDefdMacroIdentifier(PreprocessorBranch pb) { - exists(string portion | - portion = - pb.getHead() - .replaceAll("\\", " ") - .replaceAll("(", " ") - .replaceAll(")", " ") - .splitAt("&&") - .splitAt("||") and - result = portion.regexpCapture("^.*defined\\s*\\(?\\s*([a-zA-Z_][0-9a-zA-Z_]*)\\s*\\)?.*$", 1) - or - portion = "" and - pb.(PreprocessorIfdef).getHead() = result - ) -} - -class IfAndElifs extends PreprocessorBranch { - IfAndElifs() { - this instanceof PreprocessorIf or - this instanceof PreprocessorElif - } -} - -class BadIfAndElifs extends IfAndElifs { - string undefinedMacroIdentifier; - - BadIfAndElifs() { - exists(string defRM | - defRM = - this.getHead() - .regexpReplaceAll("__has_(attribute|cpp_attribute|c_attribute|builtin|include)\\s*\\(\\s*[0-9a-zA-Z_:]*\\s*\\)", - "") - .regexpReplaceAll("defined\\s*\\(?\\s*[a-zA-Z_][0-9a-zA-Z_]*\\s*\\)?", "") and - undefinedMacroIdentifier = defRM.regexpFind("(? macro '" + mi.getMacroName() + "'." diff --git a/cpp/autosar/src/rules/M3-2-2/OneDefinitionRuleViolation.ql b/cpp/autosar/src/rules/M3-2-2/OneDefinitionRuleViolation.ql index 89771eb4fa..9cbb2db425 100644 --- a/cpp/autosar/src/rules/M3-2-2/OneDefinitionRuleViolation.ql +++ b/cpp/autosar/src/rules/M3-2-2/OneDefinitionRuleViolation.ql @@ -18,7 +18,5 @@ import codingstandards.cpp.autosar import codingstandards.cpp.rules.onedefinitionruleviolation.OneDefinitionRuleViolation class OneDefinitionRuleViolationQuery extends OneDefinitionRuleViolationSharedQuery { - OneDefinitionRuleViolationQuery() { - this = ScopePackage::oneDefinitionRuleViolationQuery() - } + OneDefinitionRuleViolationQuery() { this = ScopePackage::oneDefinitionRuleViolationQuery() } } diff --git a/cpp/autosar/src/rules/M7-3-4/UsingDirectivesUsed.ql b/cpp/autosar/src/rules/M7-3-4/UsingDirectivesUsed.ql index 3c16928dc8..6168934d8d 100644 --- a/cpp/autosar/src/rules/M7-3-4/UsingDirectivesUsed.ql +++ b/cpp/autosar/src/rules/M7-3-4/UsingDirectivesUsed.ql @@ -16,8 +16,5 @@ import cpp import codingstandards.cpp.autosar from UsingDirectiveEntry u -where - not isExcluded(u, BannedSyntaxPackage::usingDirectivesUsedQuery()) and - // Exclude using unique introduced by an anonymous namespace as described in [namespace.unnamed]. - not u.getNamespace().isAnonymous() +where not isExcluded(u, BannedSyntaxPackage::usingDirectivesUsedQuery()) select u, "Use of 'using' directive." diff --git a/cpp/autosar/test/qlpack.yml b/cpp/autosar/test/qlpack.yml index db74eb8d2e..0267a585e7 100644 --- a/cpp/autosar/test/qlpack.yml +++ b/cpp/autosar/test/qlpack.yml @@ -1,4 +1,4 @@ name: autosar-cpp-coding-standards-tests -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: autosar-cpp-coding-standards extractor: cpp diff --git a/cpp/autosar/test/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.expected b/cpp/autosar/test/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.expected index 2786ab1659..6983b4ddcb 100644 --- a/cpp/autosar/test/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.expected +++ b/cpp/autosar/test/rules/A10-2-1/NonVirtualPublicOrProtectedFunctionsRedefined.expected @@ -1 +1 @@ -| test.cpp:4:8:4:9 | f1 | Member function $@ is shadowed by $@ in derived class $@ | test.cpp:4:8:4:9 | f1 | f1 | test.cpp:13:8:13:9 | f1 | this member function | test.cpp:11:7:11:13 | Derived | Derived | +| test.cpp:4:8:4:9 | f1 | Member function $@ is shadowed by $@ in derived class @a | test.cpp:4:8:4:9 | f1 | f1 | test.cpp:13:8:13:9 | f1 | this member function | test.cpp:11:7:11:13 | Derived | Derived | diff --git a/cpp/autosar/test/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.expected b/cpp/autosar/test/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.expected index f2cf6227c3..d16f6aee9c 100644 --- a/cpp/autosar/test/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.expected +++ b/cpp/autosar/test/rules/A10-3-3/VirtualFunctionsIntroducedInFinalClass.expected @@ -1,2 +1,2 @@ -| test.cpp:12:8:12:8 | g | Non-final virtual function $@ is introduced in final class $@. | test.cpp:12:8:12:8 | g | g | test.cpp:9:7:9:13 | Derived | Derived | -| test.cpp:14:16:14:16 | h | Non-final virtual function $@ is introduced in final class $@. | test.cpp:14:16:14:16 | h | h | test.cpp:9:7:9:13 | Derived | Derived | +| test.cpp:12:8:12:8 | g | Non-final virtual function $@ is introduced in final class @$. | test.cpp:12:8:12:8 | g | g | test.cpp:9:7:9:13 | Derived | Derived | +| test.cpp:14:16:14:16 | h | Non-final virtual function $@ is introduced in final class @$. | test.cpp:14:16:14:16 | h | h | test.cpp:9:7:9:13 | Derived | Derived | diff --git a/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.qlref b/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.qlref deleted file mode 100644 index 1eb9cf87cb..0000000000 --- a/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.testref b/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.testref new file mode 100644 index 0000000000..6be2f4f7ba --- /dev/null +++ b/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.testref @@ -0,0 +1 @@ +cpp/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.expected b/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.expected deleted file mode 100644 index 26e2c46ddf..0000000000 --- a/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.expected +++ /dev/null @@ -1 +0,0 @@ -| test.cpp:11:19:11:21 | msg | The format string argument to `fprintf` should be constant to prevent security issues and other potential errors. | diff --git a/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.qlref b/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.qlref deleted file mode 100644 index 55b7016be8..0000000000 --- a/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/A27-0-1/InputsFromIndependentComponentsNotValidated.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.testref b/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.testref new file mode 100644 index 0000000000..5690ee94e7 --- /dev/null +++ b/cpp/autosar/test/rules/A27-0-1/InputsFromIndependentComponentsNotValidated.testref @@ -0,0 +1 @@ +cpp/common/test/rules/nonconstantformat/NonConstantFormat.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-3-1/test.cpp b/cpp/autosar/test/rules/A3-3-1/test.cpp index 194b06329c..1bb0f9a9f0 100644 --- a/cpp/autosar/test/rules/A3-3-1/test.cpp +++ b/cpp/autosar/test/rules/A3-3-1/test.cpp @@ -29,10 +29,4 @@ static int f2() { // COMPLIANT } int main(int, char **) { // COMPLIANT -} - -namespace n { -void f5() { // COMPLIANT - int i = 0; -} -} // namespace n \ No newline at end of file +} \ No newline at end of file diff --git a/cpp/autosar/test/rules/A3-3-1/test.hpp b/cpp/autosar/test/rules/A3-3-1/test.hpp index ea5d6b7833..8fa97ca503 100644 --- a/cpp/autosar/test/rules/A3-3-1/test.hpp +++ b/cpp/autosar/test/rules/A3-3-1/test.hpp @@ -1,6 +1,4 @@ namespace n { int g; // COMPLIANT - -void f5(); // COMPLIANT -} // namespace n +} void f4(); // COMPLIANT diff --git a/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.qlref b/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.qlref deleted file mode 100644 index c0d522411a..0000000000 --- a/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.testref b/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.testref new file mode 100644 index 0000000000..7992898cfc --- /dev/null +++ b/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.testref @@ -0,0 +1 @@ +cpp/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.qlref b/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.qlref deleted file mode 100644 index 6a8b400114..0000000000 --- a/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.testref b/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.testref new file mode 100644 index 0000000000..73eb246867 --- /dev/null +++ b/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.testref @@ -0,0 +1 @@ +cpp/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.qlref b/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.qlref deleted file mode 100644 index 9a979dc1d6..0000000000 --- a/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.qlref +++ /dev/null @@ -1 +0,0 @@ -rules/M16-3-2/HashOperatorsShouldNotBeUsed.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.testref b/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.testref new file mode 100644 index 0000000000..eec0b94b11 --- /dev/null +++ b/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.testref @@ -0,0 +1 @@ +cpp/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql \ No newline at end of file diff --git a/cpp/autosar/test/rules/M7-3-4/test.cpp b/cpp/autosar/test/rules/M7-3-4/test.cpp index 992f0aee4a..54f86660d2 100644 --- a/cpp/autosar/test/rules/M7-3-4/test.cpp +++ b/cpp/autosar/test/rules/M7-3-4/test.cpp @@ -7,7 +7,3 @@ void test_using() { string s{"hello"}; } - -// Anonymous namespace introducing an using statement as specified in -// [namespace.unnamed] -namespace {} // namespace diff --git a/cpp/cert/src/codingstandards/cpp/cert.qll b/cpp/cert/src/codingstandards/cpp/cert.qll index bd64e25a0b..42bea5c327 100644 --- a/cpp/cert/src/codingstandards/cpp/cert.qll +++ b/cpp/cert/src/codingstandards/cpp/cert.qll @@ -1,3 +1,4 @@ import cpp import cert.Customizations import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.cpp.RuleMetadata diff --git a/cpp/cert/src/qlpack.yml b/cpp/cert/src/qlpack.yml index a5e0dd1a46..13f090082b 100644 --- a/cpp/cert/src/qlpack.yml +++ b/cpp/cert/src/qlpack.yml @@ -1,4 +1,4 @@ name: cert-cpp-coding-standards -version: 1.1.0 +version: 2.0.0 suites: codeql-suites libraryPathDependencies: common-cpp-coding-standards diff --git a/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked-standard.qhelp b/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked-standard.qhelp index 1c3104a8f6..51a1caec5b 100644 --- a/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked-standard.qhelp +++ b/cpp/cert/src/rules/CON50-CPP/DoNotAllowAMutexToGoOutOfScopeWhileLocked-standard.qhelp @@ -1,17 +1,74 @@
    -

    Mutex objects are used to protect shared data from being concurrently accessed. If a mutex object is destroyed while a thread is blocked waiting for the lock, critical sections and shared data are no longer protected.

    -

    The C++ Standard, [thread.mutex.class], paragraph 5 [ISO/IEC 14882-2014], states the following:

    +

    + Mutex objects are used to protect shared data from being concurrently accessed. If a mutex object is destroyed while a thread is blocked waiting for the lock, + + critical sections + + and shared data are no longer protected. +

    +

    + The C++ Standard,ย [thread.mutex.class], paragraph 5 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The behavior of a program is undefined if it destroys a mutex object owned by any thread or a thread terminates while owning a mutex object.

    +

    + The behavior of a program is undefined if it destroys a + + mutex + + object owned by any thread or a thread terminates while owning a + + mutex + + object. +

    -

    Similar wording exists for std::recursive_mutex, std::timed_mutex, std::recursive_timed_mutex, and std::shared_timed_mutex. These statements imply that destroying a mutex object while a thread is waiting on it is undefined behavior.

    +

    + Similar wording exists for + + std::recursive_mutex + + , + + std::timed_mutex + + , + + std::recursive_timed_mutex + + , and + + std::shared_timed_mutex + + .ย These statements imply that destroying a mutex object while a thread is waiting on it is + + undefined behavior + + . +

    -

    This noncompliant code example creates several threads that each invoke the do_work() function, passing a unique number as an ID.

    -

    Unfortunately, this code contains a race condition, allowing the mutex to be destroyed while it is still owned, because start_threads() may invoke the mutex's destructor before all of the threads have exited.

    - #include <mutex> +

    + This noncompliant code example creates several threads that each invoke the + + do_work() + + function, passing a unique number as an ID. +

    +

    + Unfortunately, this code containsย a race condition, allowing the mutex to be destroyed while it is still owned, because + + start_threads() + + may invoke the mutex's destructor before all of the threads have exited. +

    + + #include <mutex> #include <thread> const size_t maxThreads = 10; @@ -30,11 +87,14 @@ void start_threads() { threads[i] = std::thread(do_work, i, &m); } } - +
    -

    This compliant solution eliminates the race condition by extending the lifetime of the mutex.

    - #include <mutex> +

    + This compliant solution eliminates the race condition by extending the lifetime of the mutex. +

    + + #include <mutex> #include <thread> const size_t maxThreads = 10; @@ -54,11 +114,14 @@ void start_threads() { threads[i] = std::thread(do_work, i, &m); } } - +
    -

    This compliant solution eliminates the race condition by joining the threads before the mutex's destructor is invoked.

    - #include <mutex> +

    + This compliant solution eliminates the race condition by joining the threads before the mutex's destructor is invoked. +

    + + #include <mutex> #include <thread> const size_t maxThreads = 10; @@ -79,10 +142,13 @@ void run_threads() { for (size_t i = 0; i < maxThreads; ++i) { threads[i].join(); } -} +} +
    -

    Destroying a mutex while it is locked may result in invalid control flow and data corruption.

    +

    + Destroying a mutex while it is locked may result in invalid control flow and data corruption. +

    @@ -119,10 +185,14 @@ void run_threads() { High @@ -155,7 +225,9 @@ void run_threads() { 2021.2 @@ -170,7 +242,11 @@ void run_threads() { 2021.4 @@ -185,7 +261,9 @@ void run_threads() { 2021.2 @@ -228,7 +308,17 @@ void run_threads() {
    - P4 + + P4 + - L3 + + L3 +
    - C++4961, C++4962 + + C++4961, C++4962 + - CERT.CONC.MUTEX.DESTROY_WHILE_LOCKED + + + CERT.CONC.MUTEX.DESTROY_WHILE_LOCKED + + - CERT_CPP-CON50-a + + CERT_CPP-CON50-a + Do not destroy another thread's mutex @@ -219,7 +297,9 @@ void run_threads() { 4.4 - 4961, 4962 + + 4961, 4962 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked-standard.qhelp b/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked-standard.qhelp index 1c3104a8f6..51a1caec5b 100644 --- a/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked-standard.qhelp +++ b/cpp/cert/src/rules/CON50-CPP/DoNotDestroyAMutexWhileItIsLocked-standard.qhelp @@ -1,17 +1,74 @@
    -

    Mutex objects are used to protect shared data from being concurrently accessed. If a mutex object is destroyed while a thread is blocked waiting for the lock, critical sections and shared data are no longer protected.

    -

    The C++ Standard, [thread.mutex.class], paragraph 5 [ISO/IEC 14882-2014], states the following:

    +

    + Mutex objects are used to protect shared data from being concurrently accessed. If a mutex object is destroyed while a thread is blocked waiting for the lock, + + critical sections + + and shared data are no longer protected. +

    +

    + The C++ Standard,ย [thread.mutex.class], paragraph 5 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The behavior of a program is undefined if it destroys a mutex object owned by any thread or a thread terminates while owning a mutex object.

    +

    + The behavior of a program is undefined if it destroys a + + mutex + + object owned by any thread or a thread terminates while owning a + + mutex + + object. +

    -

    Similar wording exists for std::recursive_mutex, std::timed_mutex, std::recursive_timed_mutex, and std::shared_timed_mutex. These statements imply that destroying a mutex object while a thread is waiting on it is undefined behavior.

    +

    + Similar wording exists for + + std::recursive_mutex + + , + + std::timed_mutex + + , + + std::recursive_timed_mutex + + , and + + std::shared_timed_mutex + + .ย These statements imply that destroying a mutex object while a thread is waiting on it is + + undefined behavior + + . +

    -

    This noncompliant code example creates several threads that each invoke the do_work() function, passing a unique number as an ID.

    -

    Unfortunately, this code contains a race condition, allowing the mutex to be destroyed while it is still owned, because start_threads() may invoke the mutex's destructor before all of the threads have exited.

    - #include <mutex> +

    + This noncompliant code example creates several threads that each invoke the + + do_work() + + function, passing a unique number as an ID. +

    +

    + Unfortunately, this code containsย a race condition, allowing the mutex to be destroyed while it is still owned, because + + start_threads() + + may invoke the mutex's destructor before all of the threads have exited. +

    + + #include <mutex> #include <thread> const size_t maxThreads = 10; @@ -30,11 +87,14 @@ void start_threads() { threads[i] = std::thread(do_work, i, &m); } } - +
    -

    This compliant solution eliminates the race condition by extending the lifetime of the mutex.

    - #include <mutex> +

    + This compliant solution eliminates the race condition by extending the lifetime of the mutex. +

    + + #include <mutex> #include <thread> const size_t maxThreads = 10; @@ -54,11 +114,14 @@ void start_threads() { threads[i] = std::thread(do_work, i, &m); } } - +
    -

    This compliant solution eliminates the race condition by joining the threads before the mutex's destructor is invoked.

    - #include <mutex> +

    + This compliant solution eliminates the race condition by joining the threads before the mutex's destructor is invoked. +

    + + #include <mutex> #include <thread> const size_t maxThreads = 10; @@ -79,10 +142,13 @@ void run_threads() { for (size_t i = 0; i < maxThreads; ++i) { threads[i].join(); } -} +} +
    -

    Destroying a mutex while it is locked may result in invalid control flow and data corruption.

    +

    + Destroying a mutex while it is locked may result in invalid control flow and data corruption. +

    @@ -119,10 +185,14 @@ void run_threads() { High @@ -155,7 +225,9 @@ void run_threads() { 2021.2 @@ -170,7 +242,11 @@ void run_threads() { 2021.4 @@ -185,7 +261,9 @@ void run_threads() { 2021.2 @@ -228,7 +308,17 @@ void run_threads() {
    - P4 + + P4 + - L3 + + L3 +
    - C++4961, C++4962 + + C++4961, C++4962 + - CERT.CONC.MUTEX.DESTROY_WHILE_LOCKED + + + CERT.CONC.MUTEX.DESTROY_WHILE_LOCKED + + - CERT_CPP-CON50-a + + CERT_CPP-CON50-a + Do not destroy another thread's mutex @@ -219,7 +297,9 @@ void run_threads() { 4.4 - 4961, 4962 + + 4961, 4962 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions-standard.qhelp b/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions-standard.qhelp index 0adadc06f5..db6911a010 100644 --- a/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions-standard.qhelp +++ b/cpp/cert/src/rules/CON51-CPP/EnsureActivelyHeldLocksAreReleasedOnExceptionalConditions-standard.qhelp @@ -1,12 +1,85 @@
    -

    Mutexes that are used to protect accesses to shared data may be locked using the lock() member function and unlocked using the unlock() member function. If an exception occurs between the call to lock() and the call to unlock(), and the exception changes control flow such that unlock() is not called, the mutex will be left in the locked state and no critical sections protected by that mutex will be allowed to execute. This is likely to lead to deadlock.

    -

    The throwing of an exception must not allow a mutex to remain locked indefinitely. If a mutex was locked and an exception occurs within the critical section protected by that mutex, the mutex must be unlocked as part of exception handling before rethrowing the exception or continuing execution unless subsequent control flow will unlock the mutex.

    -

    C++ supplies the lock classes lock_guard, unique_lock, and shared_lock, which can be initialized with a mutex. In its constructor, the lock object locks the mutex, and in its destructor, it unlocks the mutex. The lock_guard class provides a simple RAII wrapper around a mutex. The unique_lock and shared_lock classes also use RAII and provide additional functionality, such as manual control over the locking strategy. The unique_lock class prevents the lock from being copied, although it allows the lock ownership to be moved to another lock. The shared_lock class allows the mutex to be shared by several locks. For all three classes, if an exception occurs and takes control flow out of the scope of the lock, the destructor will unlock the mutex and the program can continue working normally. These lock objects are the preferred way to ensure that a mutex is properly released when an exception is thrown.

    -

    Noncompliant Code Example

    -

    This noncompliant code example manipulates shared data and protects the critical section by locking the mutex. When it is finished, it unlocks the mutex. However, if an exception occurs while manipulating the shared data, the mutex will remain locked.

    - #include <mutex> +

    + Mutexes that are used to protect accesses to shared data may be locked using the + + lock() + + member function and unlocked using the + + unlock() + + member function. If an exception occurs between the call to + + lock() + + and the call to + + unlock() + + , and the exception changes control flow such that + + unlock() + + is not called, the mutex will be left in the locked state and no + + critical sections + + protected by that mutex will be allowed to execute. This is likely to lead to deadlock. +

    +

    + The throwing of an exception must not allow a mutex to remain locked indefinitely. If a mutex was locked and an exception occurs within the critical section protected by that mutex, the mutex must be unlocked as part of exception handling before rethrowing the exception or continuing execution unless subsequent control flow will unlock the mutex. +

    +

    + C++ supplies the lock classes + + lock_guard + + , + + unique_lock + + , and + + shared_lock + + , which can be initialized with a mutex. In its constructor, the lockย object locks the mutex, and in its destructor, it unlocks the mutex. The + + lock_guard + + class provides a simple + + RAII + + wrapper around a mutex.ย The + + unique_lock + + and + + shared_lock + + classes also use RAII and provide additional functionality, such as manual control over the locking strategy. The + + unique_lock + + class prevents the lock from being copied, although it allows the lock ownership to be moved to another lock. The + + shared_lock + + class allows the mutex to be shared by several locks. For all three classes, if an exception occurs and takes control flow out of the scope of the lock, the destructor will unlock the mutex and the program can continue working normally. These lock objects are the preferred way to ensure that a mutex is properly released when an exception is thrown. +

    +

    + Noncompliant Code Example +

    +

    + This noncompliant code example manipulates shared data and protects theย critical section by locking the mutex. When it is finished, it unlocks the mutex. + However, if an exception occurs while manipulating the shared data, the mutex will remain locked + . +

    + + #include <mutex> void manipulate_shared_data(std::mutex &pm) { pm.lock(); @@ -15,11 +88,14 @@ void manipulate_shared_data(std::mutex &pm) { pm.unlock(); } - +
    -

    This compliant solution catches any exceptions thrown when performing work on the shared data and unlocks the mutex before rethrowing the exception.

    - #include <mutex> +

    + This compliant solution catches any exceptions thrown when performing work on the shared data and unlocks the mutex before rethrowing the exception. +

    + + #include <mutex> void manipulate_shared_data(std::mutex &pm) { pm.lock(); @@ -30,21 +106,31 @@ void manipulate_shared_data(std::mutex &pm) { throw; } pm.unlock(); // in case no exceptions occur -} +} +
    -

    This compliant solution uses a lock_guard object to ensure that the mutex will be unlocked, even if an exception occurs, without relying on exception handling machinery and manual resource management.

    - #include <mutex> +

    + This compliant solution uses a + + lock_guard + + object to ensure that the mutex will be unlocked, even if an exception occurs, without relying on exception handling machinery and manual resource management. +

    + + #include <mutex> void manipulate_shared_data(std::mutex &pm) { std::lock_guard<std::mutex> lk(pm); // Perform work on shared data. } - +
    -

    If an exception occurs while a mutex is locked, deadlock may result.

    +

    + If an exception occurs while a mutex is locked, deadlock may result. +

    @@ -81,10 +167,14 @@ void manipulate_shared_data(std::mutex &pm) { Low @@ -117,7 +207,9 @@ void manipulate_shared_data(std::mutex &pm) { 2021.2 @@ -132,7 +224,9 @@ void manipulate_shared_data(std::mutex &pm) { 2021.2 @@ -157,10 +253,28 @@ void manipulate_shared_data(std::mutex &pm) {
    - P6 + + P6 + - L2 + + L2 +
    - C++5018 + + C++5018 + - CERT_CPP-CON51-a + + CERT_CPP-CON51-a + Do not call lock() directly on a mutex @@ -148,7 +242,9 @@ void manipulate_shared_data(std::mutex &pm) { 4.4 - 5018 + + 5018 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of ERR56-CPP. Guarantee exception safety.

    +

    + + This rule is a subset of + + ERR56-CPP. Guarantee exception safety + + . + +

    diff --git a/cpp/cert/src/rules/CON52-CPP/PreventDataRacesWhenAccessingBitFieldsFromMultipleThreads-standard.qhelp b/cpp/cert/src/rules/CON52-CPP/PreventDataRacesWhenAccessingBitFieldsFromMultipleThreads-standard.qhelp index 742e22be15..d8671cfca6 100644 --- a/cpp/cert/src/rules/CON52-CPP/PreventDataRacesWhenAccessingBitFieldsFromMultipleThreads-standard.qhelp +++ b/cpp/cert/src/rules/CON52-CPP/PreventDataRacesWhenAccessingBitFieldsFromMultipleThreads-standard.qhelp @@ -1,13 +1,26 @@
    -

    When accessing a bit-field, a thread may inadvertently access a separate bit-field in adjacent memory. This is because compilers are required to store multiple adjacent bit-fields in one storage unit whenever they fit. Consequently, data races may exist not just on a bit-field accessed by multiple threads but also on other bit-fields sharing the same byte or word. The problem is difficult to diagnose because it may not be obvious that the same memory location is being modified by multiple threads.

    -

    One approach for preventing data races in concurrent programming is to use a mutex. When properly observed by all threads, a mutex can provide safe and secure access to a shared object. However, mutexes provide no guarantees with regard to other objects that might be accessed when the mutex is not controlled by the accessing thread. Unfortunately, there is no portable way to determine which adjacent bit-fields may be stored along with the desired bit-field.

    -

    Another approach is to insert a non-bit-field member between any two bit-fields to ensure that each bit-field is the only one accessed within its storage unit. This technique effectively guarantees that no two bit-fields are accessed simultaneously.

    +

    + When accessing a bit-field, a thread may inadvertently access a separate bit-field in adjacent memory. Thisย is because compilers are required to store multiple adjacent bit-fields in one storage unit whenever they fit. Consequently, data races may exist not just on a bit-field accessed by multiple threads but also on other bit-fields sharing the same byte or word. The problem is difficultย to diagnose because it may not be obvious that the same memory location is being modified by multiple threads. +

    +

    + One approach for preventing data races in concurrent programming is to use a mutex. When properly observed by all threads, a mutex can provide safe and secure access to a shared object. However, mutexes provide no guarantees with regard to other objects that might be accessed when the mutex is not controlled by the accessing thread. Unfortunately, there is no portable way to determine which adjacent bit-fields may be stored along with the desired bit-field. +

    +

    + Another approach is to insert a non-bit-field member between any two bit-fields to ensure that each bit-field is the only one accessed within its storage unit. This technique effectively guarantees that no two bit-fields are accessed simultaneously. +

    -

    Adjacent bit-fields may be stored in a single memory location. Consequently, modifying adjacent bit-fields in different threads is undefined behavior, as shown in this noncompliant code example.

    - struct MultiThreadedFlags { +

    + Adjacent bit-fields may be stored in a single memory location. Consequently, modifying adjacent bit-fields in different threads is + + undefined behavior + + , as shown in this noncompliant code example. +

    + + struct MultiThreadedFlags { unsigned int flag1 : 2; unsigned int flag2 : 2; }; @@ -21,21 +34,28 @@ void thread1() { void thread2() { flags.flag2 = 2; } - -

    For example, the following instruction sequence is possible.

    - Thread 1: register 0 = flags + +

    + For example, the following instruction sequence is possible. +

    + + Thread 1: register 0 = flags Thread 1: register 0 &= ~mask(flag1) Thread 2: register 0 = flags Thread 2: register 0 &= ~mask(flag2) Thread 1: register 0 |= 1 << shift(flag1) Thread 1: flags = register 0 Thread 2: register 0 |= 2 << shift(flag2) -Thread 2: flags = register 0 +Thread 2: flags = register 0 +
    -

    This compliant solution protects all accesses of the flags with a mutex, thereby preventing any data races.

    - #include <mutex> - +

    + This compliant solution protects all accesses of the flags with a mutex, thereby preventing any data races. +

    + + #include <mutex> +ย  struct MultiThreadedFlags { unsigned int flag1 : 2; unsigned int flag2 : 2; @@ -57,11 +77,14 @@ void thread2() { std::lock_guard<std::mutex> lk(flags.mutex); flags.s.flag2 = 2; } - +
    -

    In this compliant solution, two threads simultaneously modify two distinct non-bit-field members of a structure. Because the members occupy different bytes in memory, no concurrency protection is required.

    - struct MultiThreadedFlags { +

    + In this compliant solution, two threads simultaneously modify two distinct non-bit-field members of a structure. Because the members occupy different bytes in memory, no concurrency protection is required. +

    + + struct MultiThreadedFlags { unsigned char flag1; unsigned char flag2; }; @@ -74,15 +97,44 @@ void thread1() { void thread2() { flags.flag2 = 2; -} -

    Unlike earlier versions of the standard, C++11 and later explicitly define a memory location and provide the following note in [intro.memory] paragraph 4 [ISO/IEC 14882-2014]:

    +} +
    +

    + Unlike earlier versions of the standard, C++11 and later explicitly define a memory location and provide the following note inย [intro.memory]ย paragraph 4 [ + + ISO/IEC 14882-2014 + + ]: +

    -

    [Note: Thus a bit-field and an adjacent non-bit-field are in separate memory locations, and therefore can be concurrently updated by two threads of execution without interference. The same applies to two bit-fields, if one is declared inside a nested struct declaration and the other is not, or if the two are separated by a zero-length bit-field declaration, or if they are separated by a non-bit-field declaration. It is not safe to concurrently update two bit-fields in the same struct if all fields between them are also bit-fields of non-zero width. โ€“ end note]

    +

    + [ + + Note: + + Thus a bit-field and an adjacent non-bit-field are in separate memory locations, and therefore can be concurrently updated by two threads of execution without interference. ย The same applies to two bit-fields, if one is declared inside a nested struct declaration and the other is not, or if the two are separated by a zero-length bit-field declaration, or if they are separated by a non-bit-field declaration. ย It is not safe to concurrently update two bit-fields in the same struct if all fields between them are also bit-fields of non-zero width. ย โ€“ + + end note + + ] +

    -

    It is almost certain that flag1 and flag2 are stored in the same word. Using a compiler that conforms to earlier versions of the standard, if both assignments occur on a thread-scheduling interleaving that ends with both stores occurring after one another, it is possible that only one of the flags will be set as intended, and the other flag will contain its previous value because both members are represented by the same word, which is the smallest unit the processor can work on. Before the changes made to the C++ Standard for C++11, there were no guarantees that these flags could be modified concurrently.

    +

    + It is almost certain that + + flag1 + + and + + flag2 + + are stored in the same word. Using a compiler that conforms to earlier versions of the standard, if both assignments occur on a thread-scheduling interleaving that ends with both stores occurring after one another, it is possible that only one of the flags will be set as intended, and the other flag will contain its previous value because both members are represented by the same word, which is the smallest unit the processor can work on. Before the changes made to the C++ Standard for C++11, there were no guarantees that these flags could be modified concurrently. +

    -

    Although the race window is narrow, an assignment or an expression can evaluate improperly because of misinterpreted data resulting in a corrupted running state or unintended information disclosure.

    +

    + Although the race window is narrow, an assignment or an expression can evaluate improperly because of misinterpreted data resulting in a corrupted running state or unintended information disclosure. +

    @@ -119,10 +171,14 @@ void thread2() { Medium @@ -155,7 +211,10 @@ void thread2() { 20.10 @@ -186,7 +247,9 @@ void thread2() { 6.5 @@ -217,7 +282,9 @@ void thread2() { 2021.2
    - P8 + + P8 + - L2 + + L2 +
    - read_write_data_racewrite_write_data_race + + read_write_data_race + write_write_data_race + Supported @@ -171,7 +230,9 @@ void thread2() { 7.2.0 - CertC++-CON52 + + CertC++-CON52 + - RACE_CONDITION + + RACE_CONDITION + Fully implemented @@ -202,7 +265,9 @@ void thread2() { 2021.2 - C++1774, C++1775 + + C++1774, C++1775 + - CERT_CPP-CON52-a + + CERT_CPP-CON52-a + Use locks to prevent race conditions when modifying bit fields @@ -251,7 +318,9 @@ void thread2() { 4.4 - 1774, 1775 + + 1774, 1775 + Enforced by MTA @@ -261,7 +330,17 @@ void thread2() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder-standard.qhelp b/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder-standard.qhelp index d2225b8ec5..aeace2b6a4 100644 --- a/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder-standard.qhelp +++ b/cpp/cert/src/rules/CON53-CPP/DeadlockByLockingInPredefinedOrder-standard.qhelp @@ -1,18 +1,61 @@
    -

    Mutexes are used to prevent multiple threads from causing a data race by accessing the same shared resource at the same time. Sometimes, when locking mutexes, multiple threads hold each other's lock, and the program consequently deadlocks. Four conditions are required for deadlock to occur:

    +

    + Mutexes are used to prevent multiple threads from causing a + + data race + + by accessing the same shared resource at the same time. Sometimes, when locking mutexes, multiple threads hold each other's lock, and the program consequently + + deadlocks + + . Four conditions are required for deadlock to occur: +

      -
    • mutual exclusion (At least one nonshareable resource must be held.),
    • -
    • hold and wait (A thread must hold a resource while awaiting availability of another resource.),
    • -
    • no preemption (Resources cannot be taken away from a thread while they are in-use.), and
    • -
    • circular wait (A thread must await a resource held by another thread which is, in turn, awaiting a resource held by the first thread.).
    • +
    • + mutual exclusion (At least one nonshareable resource must be held.), +
    • +
    • + hold and wait (A thread must hold a resource while awaiting availability of another resource.), +
    • +
    • + no preemption (Resources cannot be taken away from a thread while they are in-use.), and +
    • +
    • + circular wait (A thread must await a resource held by another thread which is, in turn, awaiting a resource held by the first thread.). +
    -

    Deadlock needs all four conditions, so preventing deadlock requires preventing any one of the four conditions. One simple solution is to lock the mutexes in a predefined order, which prevents circular wait.

    +

    + Deadlock needs all four conditions, so preventing deadlock requires preventing any one of the four conditions. One simple solution is to lock the mutexes in a predefined order, which prevents circular wait. +

    -

    The behavior of this noncompliant code example depends on the runtime environment and the platform's scheduler. The program is susceptible to deadlock if thread thr1 attempts to lock ba2's mutex at the same time thread thr2 attempts to lock ba1's mutex in the deposit() function.

    - #include <mutex> +

    + The behavior of this noncompliant code example depends on the runtime environment and the platform's scheduler. The program is susceptible to deadlock if thread + + thr1 + + attempts to lock + + ba2 + + 's mutex at the same time thread + + thr2 + + attempts to lock + + ba1 + + 's mutex in the + + deposit() + + function. +

    + + #include <mutex> #include <thread> class BankAccount { @@ -46,11 +89,27 @@ void f(BankAccount *ba1, BankAccount *ba2) { std::thread thr2(deposit, ba2, ba1, 100); thr1.join(); thr2.join(); -} +} +
    -

    This compliant solution eliminates the circular wait condition by establishing a predefined order for locking in the deposit() function. Each thread will lock on the basis of the BankAccount ID, which is set when the BankAccount object is initialized.

    - #include <atomic> +

    + This compliant solution eliminates the circular wait condition by establishing a predefined order for locking in the + + deposit() + + function. Each thread will lockย on the basis ofย the + + BankAccount + + ID, which is set when the + + BankAccount + + object is initialized. +

    + + #include <atomic> #include <mutex> #include <thread> @@ -96,18 +155,42 @@ int deposit(BankAccount *from, BankAccount *to, int amount) { } return -1; } - +ย  void f(BankAccount *ba1, BankAccount *ba2) { // Perform the deposits. std::thread thr1(deposit, ba1, ba2, 100); std::thread thr2(deposit, ba2, ba1, 100); thr1.join(); thr2.join(); -} +} +
    -

    This compliant solution uses Standard Template Library facilities to ensure that deadlock does not occur due to circular wait conditions. The std::lock() function takes a variable number of lockable objects and attempts to lock them such that deadlock does not occur [ISO/IEC 14882-2014]. In typical implementations, this is done by using a combination of lock(), try_lock(), and unlock() to attempt to lock the object and backing off if the lock is not acquired, which may have worse performance than a solution that locks in predefined order explicitly.

    - #include <mutex> +

    + This compliant solution uses Standard Template Library facilities to ensure that deadlock does not occur due to circular wait conditions. The + + std::lock() + + function takes a variable number of lockable objects and attempts to lock them such that deadlock does not occur [ + + ISO/IEC 14882-2014 + + ]. In typical implementations, this is done by using a combination of + + lock() + + , + + try_lock() + + , and + + unlock() + + to attempt to lock the object and backing off if the lock is not acquired, which may have worse performance than a solution that locks in predefined order explicitly. +

    + + #include <mutex> #include <thread> class BankAccount { @@ -135,17 +218,24 @@ int deposit(BankAccount *from, BankAccount *to, int amount) { } return -1; } - +ย  void f(BankAccount *ba1, BankAccount *ba2) { // Perform the deposits. std::thread thr1(deposit, ba1, ba2, 100); std::thread thr2(deposit, ba2, ba1, 100); thr1.join(); thr2.join(); -} +} +
    -

    Deadlock prevents multiple threads from progressing, halting program execution. A denial-of-service attack is possible if the attacker can create the conditions for deadlock.

    +

    + Deadlock prevents multiple threads from progressing, halting program execution.ย A + + denial-of-service attack + + is possible if the attacker can create the conditions for deadlock. +

    @@ -182,10 +272,14 @@ void f(BankAccount *ba1, BankAccount *ba2) { Medium @@ -215,10 +309,12 @@ void f(BankAccount *ba1, BankAccount *ba2) { @@ -265,7 +365,9 @@ void f(BankAccount *ba1, BankAccount *ba2) { 2021.2
    - P4 + + P4 + - L3 + + L3 +
    - 6.2p0 + 6.1p0 - CONCURRENCY.LOCK.ORDER + + CONCURRENCY.LOCK.ORDER + Conflicting lock order @@ -234,7 +330,9 @@ void f(BankAccount *ba1, BankAccount *ba2) { 6.5 - DEADLOCK + + DEADLOCK + Fully implemented @@ -250,7 +348,9 @@ void f(BankAccount *ba1, BankAccount *ba2) { 2021.2 - C++1772, C++1773 + + C++1772, C++1773 + - CERT_CPP-CON53-a + + CERT_CPP-CON53-a + Do not acquire locks in different order @@ -299,7 +401,9 @@ void f(BankAccount *ba1, BankAccount *ba2) { 4.4 - 1772, 1773 + + 1772, 1773 + Enforced by MTA @@ -309,7 +413,17 @@ void f(BankAccount *ba1, BankAccount *ba2) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop-standard.qhelp b/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop-standard.qhelp index 8bd65ce187..c8069ccc50 100644 --- a/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop-standard.qhelp +++ b/cpp/cert/src/rules/CON54-CPP/WrapFunctionsThatCanSpuriouslyWakeUpInLoop-standard.qhelp @@ -1,9 +1,58 @@
    -

    The wait(), wait_for(), and wait_until() member functions of the std::condition_variable class temporarily cede possession of a mutex so that other threads that may be requesting the mutex can proceed. These functions must always be called from code that is protected by locking a mutex. The waiting thread resumes execution only after it has been notified, generally as the result of the invocation of the notify_one() or notify_all() member functions invoked by another thread.

    -

    The wait() function must be invoked from a loop that checks whether a condition predicate holds. A condition predicate is an expression constructed from the variables of a function that must be true for a thread to be allowed to continue execution. The thread pauses execution via wait(), wait_for(), wait_until(), or some other mechanism, and is resumed later, presumably when the condition predicate is true and the thread is notified.

    - #include <condition_variable> +

    + The + + wait() + + , + + wait_for() + + , and + + wait_until() + + member functions of the + + std::condition_variable + + class temporarily cede possession of a mutex so that other threads that may be requesting the mutex can proceed. These functionsย must always be called from code that is protected by locking a mutex. The waiting thread resumes execution only after it has been notified, generally as the result of the invocation of the + + notify_one() + + or + + notify_all() + + member functions invoked by another thread. +

    +

    + The + + wait() + + function must be invoked from a loop that checks whether a + + condition predicate + + holds. A condition predicate is an expression constructed from the variables of a function that must be true for a thread to be allowed to continue execution. The thread pauses execution via + + wait() + + , + + wait_for() + + , + + wait_until() + + , or some other mechanism, and is resumed later, presumably when the condition predicate is true and the thread is notified. +

    + + #include <condition_variable> #include <mutex> extern bool until_finish(void); @@ -18,15 +67,71 @@ void func(void) { } // Resume when condition holds. -} -

    The notification mechanism notifies the waiting thread and allows it to check its condition predicate. The invocation of notify_all() in another thread cannot precisely determine which waiting thread will be resumed. Condition predicate statements allow notified threads to determine whether they should resume upon receiving the notification.

    +} +
    +

    + The notification mechanism notifies the waiting thread and allows it to check its condition predicate. The invocation of + + notify_all() + + in another thread cannot precisely determine which waiting thread will be resumed. Condition predicate statements allow notified threads to determine whether they should resume upon receiving the notification. +

    -

    This noncompliant code example monitors a linked list and assigns one thread to consume list elements when the list is nonempty.

    -

    This thread pauses execution using wait() and resumes when notified, presumably when the list has elements to be consumed. It is possible for the thread to be notified even if the list is still empty, perhaps because the notifying thread used notify_all(), which notifies all threads. Notification using notify_all() is frequently preferred over using notify_one(). (See CON55-CPP. Preserve thread safety and liveness when using condition variables for more information.)

    -

    A condition predicate is typically the negation of the condition expression in the loop. In this noncompliant code example, the condition predicate for removing an element from a linked list is (list->next != nullptr), whereas the condition expression for the while loop condition is (list->next == nullptr).

    -

    This noncompliant code example nests the call to wait() inside an if block and consequently fails to check the condition predicate after the notification is received. If the notification was spurious or malicious, the thread would wake up prematurely.

    - #include <condition_variable> +

    + This noncompliant code example monitors a linked list and assigns one thread to consume list elements when the list is nonempty. +

    +

    + This thread pauses execution using + + wait() + + and resumes when notified, presumably when the list has elements to be consumed. It is possible for the thread to be notified even if the list is still empty, perhaps because the notifying thread used + + notify_all() + + , which notifies all threads. Notification using + + notify_all() + + is frequently preferred over using + + notify_one() + + . (See + + CON55-CPP. Preserve thread safety and liveness when using condition variables + + for more information.) +

    +

    + Aย condition predicate is typically the negation of the condition expression in the loop. In this noncompliant code example, the condition predicate for removing an element from a linked list is + + (list->next != nullptr) + + , whereas the condition expression for the + + while + + loop condition is + + (list->next == nullptr) + + . +

    +

    + This noncompliant code example nests the call to + + wait() + + inside an + + if + + block and consequently fails to check the condition predicate after the notification is received. If the notification was spurious or malicious, the thread would wake up prematurely. +

    + + #include <condition_variable> #include <mutex> struct Node { @@ -46,11 +151,27 @@ void consume_list_element(std::condition_variable &condition) { } // Proceed when condition holds. -} +} +
    -

    This compliant solution calls the wait() member function from within a while loop to check the condition both before and after the call to wait().

    - #include <condition_variable> +

    + This compliant solution calls the + + wait() + + member function from within a + + while + + loop to check the condition both before and after the call to + + wait() + + . +

    + + #include <condition_variable> #include <mutex> struct Node { @@ -70,11 +191,31 @@ void consume_list_element() { } // Proceed when condition holds. -} +} +
    -

    The std::condition_variable::wait() function has an overloaded form that accepts a function object representing the predicate. This form of wait() behaves as if it were implemented as while (!pred()) wait(lock);. This compliant solution uses a lambda as a predicate and passes it to the wait() function. The predicate is expected to return true when it is safe to proceed, which reverses the predicate logic from the compliant solution using an explicit loop predicate.

    - #include <condition_variable> +

    + The + + std::condition_variable::wait() + + function has an overloaded form that accepts a function object representing the predicate. This form of + + wait() + + behaves as if it were implemented as + + while (!pred()) wait(lock); + + . This compliant solution uses a lambda as a predicate and passes it to the + + wait() + + function. The predicate is expected to return true when it is safe to proceed, which reverses the predicate logic from the compliant solution using an explicit loop predicate. +

    + + #include <condition_variable> #include <mutex> struct Node { @@ -88,13 +229,36 @@ static std::condition_variable condition; void consume_list_element() { std::unique_lock<std::mutex> lk(m); - +ย  condition.wait(lk, []{ return list.next; }); // Proceed when condition holds. -} +} +
    -

    Failure to enclose calls to the wait(), wait_for(), or wait_until() member functions inside a while loop can lead to indefinite blocking and denial of service (DoS).

    +

    + Failure to enclose calls to the + + wait() + + , + + wait_for() + + , or + + wait_until() + + member functions inside a + + while + + loop can lead to indefinite blocking and + + denial of service + + (DoS). +

    @@ -131,10 +295,14 @@ void consume_list_element() { Medium @@ -167,7 +335,9 @@ void consume_list_element() { 2021.2 @@ -182,7 +352,11 @@ void consume_list_element() { 2021.4 @@ -197,7 +371,9 @@ void consume_list_element() { 2021.2 @@ -240,7 +418,17 @@ void consume_list_element() {
    - P2 + + P2 + - L3 + + L3 +
    - C++5019 + + C++5019 + - CERT.CONC.WAKE_IN_LOOP + + + CERT.CONC.WAKE_IN_LOOP + + - CERT_CPP-CON54-a + + CERT_CPP-CON54-a + Wrap functions that can spuriously wake up in a loop @@ -231,7 +407,9 @@ void consume_list_element() { 4.4 - 5019 + + 5019 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -297,7 +485,9 @@ void consume_list_element() { diff --git a/cpp/cert/src/rules/CON55-CPP/PreserveThreadSafetyAndLivenessWhenUsingConditionVariables-standard.qhelp b/cpp/cert/src/rules/CON55-CPP/PreserveThreadSafetyAndLivenessWhenUsingConditionVariables-standard.qhelp index 4be9e63e12..cbd34c40dd 100644 --- a/cpp/cert/src/rules/CON55-CPP/PreserveThreadSafetyAndLivenessWhenUsingConditionVariables-standard.qhelp +++ b/cpp/cert/src/rules/CON55-CPP/PreserveThreadSafetyAndLivenessWhenUsingConditionVariables-standard.qhelp @@ -1,26 +1,168 @@
    -

    Both thread safety and liveness are concerns when using condition variables. The thread-safety property requires that all objects maintain consistent states in a multithreaded environment [Lea 2000]. The liveness property requires that every operation or function invocation execute to completion without interruption; for example, there is no deadlock.

    -

    Condition variables must be used inside a while loop. (See CON54-CPP. Wrap functions that can spuriously wake up in a loop for more information.) To guarantee liveness, programs must test the while loop condition before invoking the condition_variable::wait() member function. This early test checks whether another thread has already satisfied the condition predicate and has sent a notification. Invoking wait() after the notification has been sent results in indefinite blocking.

    -

    To guarantee thread safety, programs must test the while loop condition after returning from wait(). When a given thread invokes wait(), it will attempt to block until its condition variable is signaled by a call to condition_variable::notify_all() or to condition_variable::notify_one().

    -

    The notify_one() member function unblocks one of the threads that are blocked on the specified condition variable at the time of the call. If multiple threads are waiting on the same condition variable, the scheduler can select any of those threads to be awakened (assuming that all threads have the same priority level).

    -

    The notify_all() member function unblocks all of the threads that are blocked on the specified condition variable at the time of the call. The order in which threads execute following a call to notify_all() is unspecified. Consequently, an unrelated thread could start executing, discover that its condition predicate is satisfied, and resume execution even though it was supposed to remain dormant.

    -

    For these reasons, threads must check the condition predicate after the wait() function returns. A while loop is the best choice for checking the condition predicate both before and after invoking wait().

    -

    The use of notify_one() is safe if each thread uses a unique condition variable. If multiple threads share a condition variable, the use of notify_one() is safe only if the following conditions are met:

    +

    + Both thread safety and + + liveness + + are concerns when using condition variables. The + + thread-safety + + property requires that all objects maintain consistent states in a multithreaded environment [ + + Lea 2000 + + ]. The + + liveness + + property requires that every operation or function invocation execute to completion without interruption; for example, there is no deadlock. +

    +

    + Condition variables must be used inside a + + while + + loop. (See + + CON54-CPP. Wrap functions that can spuriously wake up in a loop + + for more information.) To guarantee liveness, programs must test the + + while + + loop condition before invoking the + + condition_variable::wait() + + member function. This early test checks whether another thread has already satisfied the + + condition predicate + + and has sent a notification. Invoking + + wait() + + after the notification has been sent results in indefinite blocking. +

    +

    + To guarantee thread safety, programs must test the + + while + + loop condition after returning from + + wait() + + . When a given thread invokes + + wait() + + , it will attempt to block until its condition variable is signaled by a call to + + condition_variable::notify_all() + + or to + + condition_variable::notify_one() + + . +

    +

    + The + + notify_one() + + member function unblocks one of the threads that are blocked on the specified condition variable at the time of the call. If multiple threads are waiting on the same condition variable, the scheduler can select any of those threads to be awakened (assuming that all threads have the same priority level). +

    +

    + The + + notify_all() + + member function unblocks all of the threads that are blocked on the specified condition variable at the time of the call. The order in which threads execute following a call to + + notify_all() + + is unspecified. Consequently, an unrelated thread could start executing, discover that its condition predicate is satisfied, and resume execution even though it was supposed to remain dormant. +

    +

    + For these reasons, threads must check the condition predicate after the + + wait() + + function returns. A + + while + + loop is the best choice for checking the condition predicate both before and after invoking + + wait() + + . +

    +

    + The use of + + notify_one() + + is safe if each thread uses a unique condition variable. If multiple threads share a condition variable, the use of + + notify_one() + + is safe only if the following conditions are met: +

      -
    • All threads must perform the same set of operations after waking up, which means that any thread can be selected to wake up and resume for a single invocation of notify_one().
    • -
    • Only one thread is required to wake upon receiving the signal.
    • +
    • + All threads must perform the same set of operations after waking up, whichย means that any thread can be selected to wake up and resume for a single invocation of + + notify_one() + + . +
    • +
    • + Only one thread is required to wake upon receiving the signal. +
    -

    The notify_all() function can be used to unblock all of the threads that are blocked on the specified condition variable if the use of notify_one() is unsafe.

    +

    + The + + notify_all() + + function can be used to unblock all of the threads that are blocked on the specified condition variable if the use of + + notify_one() + + is unsafe. +

    -

    This noncompliant code example uses five threads that are intended to execute sequentially according to the step level assigned to each thread when it is created (serialized processing). The currentStep variable holds the current step level and is incremented when the respective thread completes. Finally, another thread is signaled so that the next step can be executed. Each thread waits until its step level is ready, and the wait() call is wrapped inside a while loop, in compliance with CON54-CPP. Wrap functions that can spuriously wake up in a loop.

    - #include <condition_variable> +

    + This noncompliant code exampleย uses five threadsย that are intended to executeย sequentially according to the step level assigned to each thread when it is created (serialized processing). The + + currentStep + + variable holds the current step level and is incrementedย when the respective thread completes. Finally, another thread is signaled so that the next step can be executed. Each thread waits until its step level is ready, and the + + wait() + + call is wrapped inside a + + while + + loop, in compliance with + + CON54-CPP. Wrap functions that can spuriously wake up in a loop. + +

    + + #include <condition_variable> #include <iostream> #include <mutex> #include <thread> - +ย  std::mutex mutex; std::condition_variable cond; @@ -59,9 +201,20 @@ int main() { for (size_t i = numThreads; i != 0; --i) { threads[i - 1].join(); } -} -

    In this example, all threads share a single condition variable. Each thread has its own distinct condition predicate because each thread requires currentStep to have a different value before proceeding. When the condition variable is signaled, any of the waiting threads can wake up. The following table illustrates a possible scenario in which the liveness property is violated. If, by chance, the notified thread is not the thread with the next step value, that thread will wait again. No additional notifications can occur, and eventually the pool of available threads will be exhausted.

    -

    Deadlock: Out-of-Sequence Step Value

    +} +
    +

    + In this example, all threads share a single condition variable. Each thread has its own distinct condition predicate because each thread requires + + currentStep + + to have a different value before proceeding. When the condition variable is signaled, any of the waiting threads can wake up. The following table illustrates a possible scenario in which the liveness property is violated. If, by chance, the notified thread is not the thread with the next step value, that thread will wait again. No additional notifications can occur, and eventually the pool of available threads will be exhausted. +

    +

    + + Deadlock: Out-of-Sequence Step Value + +

    7.17.7.4, "The - atomic_compare_exchange + + atomic_compare_exchange + Generic Functions"
    @@ -71,11 +224,15 @@ int main() { @@ -107,8 +266,10 @@ int main() { 0 @@ -122,8 +283,10 @@ int main() { 0 @@ -138,7 +301,9 @@ int main() { @@ -153,7 +318,9 @@ int main() { @@ -168,7 +335,9 @@ int main() { @@ -182,17 +351,32 @@ int main() { โ€”
    Thread # ( - my_step + + my_step + ) - current_step + + current_step + Action @@ -93,7 +250,9 @@ int main() { Thread 3 executes the first time: the predicate is - false -> wait() + + false -> wait() +
    - Thread 2 executes the first time: the predicate is - false -> wait() + Thread 2 executes the first time: theย predicate is + + false -> wait() +
    - Thread 4 executes the first time: the predicate is - false -> wait() + Thread 4 executes theย first time: the predicate is + + false -> wait() +
    Thread 0 executes the first time: the predicate is - true -> currentStep++; notify_one() + + true -> currentStep++; notify_one() +
    Thread 1 executes the first time: the predicate is - true -> currentStep++; notify_one() + + true -> currentStep++; notify_one() +
    Thread 3 wakes up (scheduler choice): the predicate is - false -> wait() + + false -> wait() +
    - Thread exhaustion! + + Thread exhaustion! + There are no more threads to run, and a conditional variable signal is needed to wake up the others.
    -

    This noncompliant code example violates the liveness property.

    +

    + This noncompliant code example violates the liveness property. +

    -

    This compliant solution uses notify_all() to signal all waiting threads instead of a single random thread. Only the run_step() thread code from the noncompliant code example is modified.

    - #include <condition_variable> +

    + This compliant solution uses + + notify_all() + + to signal all waiting threads instead of a single random thread.ย Only the + + run_step() + + thread code from the noncompliant code example is modified. +

    + + #include <condition_variable> #include <iostream> #include <mutex> #include <thread> @@ -221,14 +405,31 @@ void run_step(size_t myStep) { std::cout << "Thread " << myStep << " is exiting..." << std::endl; } - -// ... main() unchanged ... -

    Awakening all threads guarantees the liveness property because each thread will execute its condition predicate test, and exactly one will succeed and continue execution.

    +ย  +// ... main() unchanged ... +
    +

    + Awakening all threads guarantees the liveness property becauseย each thread willย execute itsย condition predicate test, and exactly one will succeed and continue execution. +

    -

    Another compliant solution is to use a unique condition variable for each thread (all associated with the same mutex). In this case, notify_one() wakes up only the thread that is waiting on it. This solution is more efficient than using notify_all() because only the desired thread is awakened.

    -

    The condition predicate of the signaled thread must be true; otherwise, a deadlock will occur.

    - #include <condition_variable> +

    + Another compliant solution is to use a unique condition variable for each thread (all associated with the same mutex). In this case, + + notify_one() + + wakes up only the thread that is waiting on it. + This solution is more efficient than using + + notify_all() + + because only the desired threadย is awakened. +

    +

    + Theย condition predicate of the signaled thread must be true; otherwise, a deadlock will occur. +

    + + #include <condition_variable> #include <iostream> #include <mutex> #include <thread> @@ -262,10 +463,17 @@ void run_step(size_t myStep) { std::cout << "Thread " << myStep << " is exiting..." << std::endl; } -// ... main() unchanged ... +// ... main() unchanged ... +
    -

    Failing to preserve the thread safety and liveness of a program when using condition variables can lead to indefinite blocking and denial of service (DoS).

    +

    + Failing to preserve the thread safety and liveness of a program when using condition variables can lead to indefinite blocking and + + denial of service + + (DoS). +

    @@ -302,10 +510,14 @@ void run_step(size_t myStep) { Medium @@ -338,7 +550,9 @@ void run_step(size_t myStep) { 2021.2 @@ -353,7 +567,11 @@ void run_step(size_t myStep) { 2021.4 @@ -368,7 +586,9 @@ void run_step(size_t myStep) { 2021.2 @@ -393,7 +615,17 @@ void run_step(size_t myStep) {
    - P2 + + P2 + - L3 + + L3 +
    - C++1778, C++1779 + + C++1778, C++1779 + - CERT.CONC.UNSAFE_COND_VAR + + + CERT.CONC.UNSAFE_COND_VAR + + - CERT_CPP-CON55-a + + CERT_CPP-CON55-a + Do not use the 'notify_one()' function when multiple threads are waiting on the same condition variable @@ -384,7 +604,9 @@ void run_step(size_t myStep) { 4.4 - 5020 + + 5020 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -450,9 +682,13 @@ void run_step(size_t myStep) { diff --git a/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex-standard.qhelp b/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex-standard.qhelp index d08bb5af65..31945b5715 100644 --- a/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex-standard.qhelp +++ b/cpp/cert/src/rules/CON56-CPP/DoNotSpeculativelyLockALockedNonRecursiveMutex-standard.qhelp @@ -1,24 +1,175 @@
    -

    The C++ Standard Library supplies both recursive and non-recursive mutex classes used to protect critical sections. The recursive mutex classes (std::recursive_mutex and std::recursive_timed_mutex) differ from the non-recursive mutex classes (std::mutex, std::timed_mutex, and std::shared_timed_mutex) in that a recursive mutex may be locked recursively by the thread that currently owns the mutex. All mutex classes support the ability to speculatively lock the mutex through functions such as try_lock(), try_lock_for(), try_lock_until(), try_lock_shared_for(), and try_lock_shared_until(). These speculative locking functions attempt to obtain ownership of the mutex for the calling thread, but will not block in the event the ownership cannot be obtained. Instead, they return a Boolean value specifying whether the ownership of the mutex was obtained or not.

    -

    The C++ Standard, [thread.mutex.requirements.mutex], paragraphs 14 and 15 [ISO/IEC 14882-2014], state the following:

    +

    + The C++ Standard Library supplies both recursive and non-recursive mutex classes used to protect + + critical sections + + . The recursive mutex classes ( + + std::recursive_mutex + + and + + std::recursive_timed_mutex + + ) differ from the non-recursive mutex classes ( + + std::mutex + + , + + std::timed_mutex + + , and + + std::shared_timed_mutex + + ) in that a recursive mutex may be locked recursively by the thread that currently owns the mutex. All mutex classes support the ability to speculatively lock the mutex through functions such as + + try_lock() + + , + + try_lock_for() + + , + + try_lock_until() + + , + + try_lock_shared_for() + + , and + + try_lock_shared_until() + + . These speculative locking functions attempt to obtain ownership of the mutex for the calling thread, but will not block in the event the ownership cannot be obtained. Instead, they return a Boolean value specifying whether the ownership of the mutex was obtained or not. +

    +

    + The C++ Standard,ย [thread.mutex.requirements.mutex], paragraphs 14 and 15ย [ + + ISO/IEC 14882-2014 + + ], state the following: +

    -

    The expression m.try_lock() shall be well-formed and have the following semantics:Requires: If m is of type std::mutex, std::timed_mutex, or std::shared_timed_mutex, the calling thread does not own the mutex.

    +

    + The expression + + m.try_lock() + + shall be well-formed and have the following semantics: + Requires: If + + m + + is of type + + std::mutex + + , + + std::timed_mutex + + , or + + std::shared_timed_mutex + + , the callingย thread does not own the mutex. +

    -

    Further, [thread.timedmutex.class], paragraph 3, in part, states the following:

    +

    + Further, + [thread.timedmutex.class], paragraph 3, in part, states the following: +

    -

    The behavior of a program is undefined if:โ€” a thread that owns a timed_mutex object calls lock(), try_lock(), try_lock_for(), or try_lock_until() on that object

    +

    + The behavior of a program is undefined if: + โ€” a thread that owns a + + timed_mutex + + object calls + + lock() + + , + + try_lock() + + , + + try_lock_for() + + , or + + try_lock_until() + + on that object +

    -

    Finally, [thread.sharedtimedmutex.class], paragraph 3, in part, states the following:

    +

    + Finally, [thread.sharedtimedmutex.class], paragraph 3, in part, states the following: +

    -

    The behavior of a program is undefined if:โ€” a thread attempts to recursively gain any ownership of a shared_timed_mutex.

    +

    + The behavior of a program is undefined if: + โ€” a thread attempts to recursively gain any ownership of a + + shared_timed_mutex + + . +

    -

    Thus, attempting to speculatively lock a non-recursive mutex object that is already owned by the calling thread is undefined behavior. Do not call try_lock(), try_lock_for(), try_lock_until(), try_lock_shared_for(), or try_lock_shared_until() on a non-recursive mutex object from a thread that already owns that mutex object.

    +

    + Thus, attempting to speculatively lock a non-recursive mutex object that is already owned by the calling thread is + + undefined behavior + + . Do not call + + try_lock() + + , + + try_lock_for() + + , + + try_lock_until() + + , + + try_lock_shared_for() + + ,ย or + + try_lock_shared_until() + + on a non-recursive mutex object from a thread that already owns that mutex object. +

    -

    In this noncompliant code example, the mutex m is locked by the thread's initial entry point and is speculatively locked in the do_work() function from the same thread, resulting in undefined behavior because it is not a recursive mutex. With common implementations, this may result in deadlock.

    - #include <mutex> +

    + In this noncompliant code example, the mutex + + m + + is locked by the thread's initial entry point and is speculatively locked in the + + do_work() + + function from the same thread, resulting in undefined behavior because it is not a recursive mutex. With common implementations, this may result in + + deadlock + + . +

    + + #include <mutex> #include <thread> std::mutex m; @@ -55,11 +206,14 @@ int main() { t.join(); } - +
    -

    This compliant solution removes the lock from the thread's initial entry point, allowing the mutex to be speculatively locked, but not recursively.

    - #include <mutex> +

    + This compliant solution removes the lock from the thread's initial entry point, allowing the mutex to be speculatively locked, but not recursively. +

    + + #include <mutex> #include <thread> std::mutex m; @@ -93,10 +247,13 @@ int main() { do_work(); t.join(); -} +} +
    -

    Speculatively locking a non-recursive mutex in a recursive manner is undefined behavior that can lead to deadlock.

    +

    + Speculatively locking a non-recursive mutex in a recursive manner is undefined behavior that can lead to deadlock. +

    XSH, System Interfaces, - pthread_cond_broadcast + + pthread_cond_broadcast + XSH, System Interfaces, - pthread_cond_signal + + pthread_cond_signal +
    @@ -133,10 +290,14 @@ int main() { High @@ -169,7 +330,9 @@ int main() { 2021.2 @@ -184,7 +347,9 @@ int main() { 2021.2
    - P1 + + P1 + - L3 + + L3 +
    - C++4986, C++4987 + + C++4986, C++4987 + - CERT_CPP-CON56-a + + CERT_CPP-CON56-a + Avoid double locking @@ -194,7 +359,17 @@ int main() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit-standard.qhelp b/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit-standard.qhelp index d08bb5af65..31945b5715 100644 --- a/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit-standard.qhelp +++ b/cpp/cert/src/rules/CON56-CPP/LockedALockedNonRecursiveMutexAudit-standard.qhelp @@ -1,24 +1,175 @@
    -

    The C++ Standard Library supplies both recursive and non-recursive mutex classes used to protect critical sections. The recursive mutex classes (std::recursive_mutex and std::recursive_timed_mutex) differ from the non-recursive mutex classes (std::mutex, std::timed_mutex, and std::shared_timed_mutex) in that a recursive mutex may be locked recursively by the thread that currently owns the mutex. All mutex classes support the ability to speculatively lock the mutex through functions such as try_lock(), try_lock_for(), try_lock_until(), try_lock_shared_for(), and try_lock_shared_until(). These speculative locking functions attempt to obtain ownership of the mutex for the calling thread, but will not block in the event the ownership cannot be obtained. Instead, they return a Boolean value specifying whether the ownership of the mutex was obtained or not.

    -

    The C++ Standard, [thread.mutex.requirements.mutex], paragraphs 14 and 15 [ISO/IEC 14882-2014], state the following:

    +

    + The C++ Standard Library supplies both recursive and non-recursive mutex classes used to protect + + critical sections + + . The recursive mutex classes ( + + std::recursive_mutex + + and + + std::recursive_timed_mutex + + ) differ from the non-recursive mutex classes ( + + std::mutex + + , + + std::timed_mutex + + , and + + std::shared_timed_mutex + + ) in that a recursive mutex may be locked recursively by the thread that currently owns the mutex. All mutex classes support the ability to speculatively lock the mutex through functions such as + + try_lock() + + , + + try_lock_for() + + , + + try_lock_until() + + , + + try_lock_shared_for() + + , and + + try_lock_shared_until() + + . These speculative locking functions attempt to obtain ownership of the mutex for the calling thread, but will not block in the event the ownership cannot be obtained. Instead, they return a Boolean value specifying whether the ownership of the mutex was obtained or not. +

    +

    + The C++ Standard,ย [thread.mutex.requirements.mutex], paragraphs 14 and 15ย [ + + ISO/IEC 14882-2014 + + ], state the following: +

    -

    The expression m.try_lock() shall be well-formed and have the following semantics:Requires: If m is of type std::mutex, std::timed_mutex, or std::shared_timed_mutex, the calling thread does not own the mutex.

    +

    + The expression + + m.try_lock() + + shall be well-formed and have the following semantics: + Requires: If + + m + + is of type + + std::mutex + + , + + std::timed_mutex + + , or + + std::shared_timed_mutex + + , the callingย thread does not own the mutex. +

    -

    Further, [thread.timedmutex.class], paragraph 3, in part, states the following:

    +

    + Further, + [thread.timedmutex.class], paragraph 3, in part, states the following: +

    -

    The behavior of a program is undefined if:โ€” a thread that owns a timed_mutex object calls lock(), try_lock(), try_lock_for(), or try_lock_until() on that object

    +

    + The behavior of a program is undefined if: + โ€” a thread that owns a + + timed_mutex + + object calls + + lock() + + , + + try_lock() + + , + + try_lock_for() + + , or + + try_lock_until() + + on that object +

    -

    Finally, [thread.sharedtimedmutex.class], paragraph 3, in part, states the following:

    +

    + Finally, [thread.sharedtimedmutex.class], paragraph 3, in part, states the following: +

    -

    The behavior of a program is undefined if:โ€” a thread attempts to recursively gain any ownership of a shared_timed_mutex.

    +

    + The behavior of a program is undefined if: + โ€” a thread attempts to recursively gain any ownership of a + + shared_timed_mutex + + . +

    -

    Thus, attempting to speculatively lock a non-recursive mutex object that is already owned by the calling thread is undefined behavior. Do not call try_lock(), try_lock_for(), try_lock_until(), try_lock_shared_for(), or try_lock_shared_until() on a non-recursive mutex object from a thread that already owns that mutex object.

    +

    + Thus, attempting to speculatively lock a non-recursive mutex object that is already owned by the calling thread is + + undefined behavior + + . Do not call + + try_lock() + + , + + try_lock_for() + + , + + try_lock_until() + + , + + try_lock_shared_for() + + ,ย or + + try_lock_shared_until() + + on a non-recursive mutex object from a thread that already owns that mutex object. +

    -

    In this noncompliant code example, the mutex m is locked by the thread's initial entry point and is speculatively locked in the do_work() function from the same thread, resulting in undefined behavior because it is not a recursive mutex. With common implementations, this may result in deadlock.

    - #include <mutex> +

    + In this noncompliant code example, the mutex + + m + + is locked by the thread's initial entry point and is speculatively locked in the + + do_work() + + function from the same thread, resulting in undefined behavior because it is not a recursive mutex. With common implementations, this may result in + + deadlock + + . +

    + + #include <mutex> #include <thread> std::mutex m; @@ -55,11 +206,14 @@ int main() { t.join(); } - +
    -

    This compliant solution removes the lock from the thread's initial entry point, allowing the mutex to be speculatively locked, but not recursively.

    - #include <mutex> +

    + This compliant solution removes the lock from the thread's initial entry point, allowing the mutex to be speculatively locked, but not recursively. +

    + + #include <mutex> #include <thread> std::mutex m; @@ -93,10 +247,13 @@ int main() { do_work(); t.join(); -} +} +
    -

    Speculatively locking a non-recursive mutex in a recursive manner is undefined behavior that can lead to deadlock.

    +

    + Speculatively locking a non-recursive mutex in a recursive manner is undefined behavior that can lead to deadlock. +

    @@ -133,10 +290,14 @@ int main() { High @@ -169,7 +330,9 @@ int main() { 2021.2 @@ -184,7 +347,9 @@ int main() { 2021.2
    - P1 + + P1 + - L3 + + L3 +
    - C++4986, C++4987 + + C++4986, C++4987 + - CERT_CPP-CON56-a + + CERT_CPP-CON56-a + Avoid double locking @@ -194,7 +359,17 @@ int main() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert-standard.qhelp b/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert-standard.qhelp index f6e745c17b..0d08776b1d 100644 --- a/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert-standard.qhelp +++ b/cpp/cert/src/rules/CTR50-CPP/ContainerAccessWithoutRangeCheckCert-standard.qhelp @@ -1,35 +1,96 @@
    -

    Ensuring that array references are within the bounds of the array is almost entirely the responsibility of the programmer. Likewise, when using standard template library vectors, the programmer is responsible for ensuring integer indexes are within the bounds of the vector.

    +

    + Ensuring that array references are within the bounds of the array is almost entirely the responsibility of the programmer. Likewise, when using standard template library vectors, the programmer is responsible for ensuring integer indexes are within the bounds of the vector. +

    -

    This noncompliant code example shows a function, insert_in_table(), that has two int parameters, pos and value, both of which can be influenced by data originating from untrusted sources. The function performs a range check to ensure that pos does not exceed the upper bound of the array, specified by tableSize, but fails to check the lower bound. Because pos is declared as a (signed) int, this parameter can assume a negative value, resulting in a write outside the bounds of the memory referenced by table.

    - #include <cstddef> - +

    + This noncompliant code example shows a function, + + insert_in_table() + + , that has two + + int + + parameters, + + pos + + and + + value + + , both of which can be influenced by data originating from untrusted sources.ย The function performs a range check to ensure that + + pos + + does not exceed the upper bound of the array, specified by + + tableSize + + , but fails to check the lower bound. Because + + pos + + is declared as a (signed) + + int + + , this parameter can assume a negative value, resulting in a write outside the bounds of the memory referenced by + + table + + . +

    + + #include <cstddef> +ย  void insert_in_table(int *table, std::size_t tableSize, int pos, int value) { if (pos >= tableSize) { // Handle error return; } table[pos] = value; -} +} +
    -

    In this compliant solution, the parameter pos is declared as size_t, which prevents the passing of negative arguments.

    - #include <cstddef> - +

    + In this compliant solution, the parameter + + pos + + is declared as + + size_t + + , which prevents theย passing of negative arguments. +

    + + #include <cstddef> +ย  void insert_in_table(int *table, std::size_t tableSize, std::size_t pos, int value) { if (pos >= tableSize) { // Handle error return; } table[pos] = value; -} +} +
    -

    Non-type templates can be used to define functions accepting an array type where the array bounds are deduced at compile time. This compliant solution is functionally equivalent to the previous bounds-checking one except that it additionally supports calling insert_in_table() with an array of known bounds.

    - #include <cstddef> +

    + Non-type templates can be used to define functions accepting an array type where the array bounds are deduced at compile time. This compliant solution is functionally equivalent to the previous bounds-checking one except that it additionally supports calling + + insert_in_table() + + with an array of known bounds. +

    + + #include <cstddef> #include <new> void insert_in_table(int *table, std::size_t tableSize, std::size_t pos, int value) { // #1 @@ -44,7 +105,7 @@ template <std::size_t N> void insert_in_table(int (&table)[N], std::size_t pos, int value) { // #2 insert_in_table(table, N, pos, value); } - +ย  void f() { // Exposition only int table1[100]; @@ -54,11 +115,51 @@ void f() { insert_in_table(table1, 100, 0, 0); // Calls #1 insert_in_table(table2, 100, 0, 0); // Calls #1 delete [] table2; -} +} +
    -

    In this noncompliant code example, a std::vector is used in place of a pointer and size pair. The function performs a range check to ensure that pos does not exceed the upper bound of the container. Because pos is declared as a (signed) long long, this parameter can assume a negative value. On systems where std::vector::size_type is ultimately implemented as an unsigned int (such as with Microsoft Visual Studio 2013), the usual arithmetic conversions applied for the comparison expression will convert the unsigned value to a signed value. If pos has a negative value, this comparison will not fail, resulting in a write outside the bounds of the std::vector object when the negative value is interpreted as a large unsigned value in the indexing operator.

    - #include <vector> +

    + In this noncompliant code example, a + + std::vector + + is used in place of a pointer and size pair.ย The function performs a range check to ensure that + + pos + + does not exceed the upper bound of the container. Because + + pos + + is declared as a (signed) + + long long + + , this parameter can assume a negative value. On systems where + + std::vector::size_type + + is ultimately implemented as an + + unsigned int + + (such as with + + Microsoft Visual Studio + + 2013), the usual arithmetic conversions applied for the comparison expression will convert the unsigned value to a signed value. If + + pos + + has a negative value, this comparison will not fail, resulting in a write outside the bounds of the + + std::vector + + object when the negative value is interpreted as a large unsigned value in the indexing operator. +

    + + #include <vector> void insert_in_table(std::vector<int> &table, long long pos, int value) { if (pos >= table.size()) { @@ -67,11 +168,22 @@ void insert_in_table(std::vector<int> &table, long long pos, int value } table[pos] = value; } - +
    -

    In this compliant solution, the parameter pos is declared as size_t, which ensures that the comparison expression will fail when a large, positive value (converted from a negative argument) is given.

    - #include <vector> +

    + In this compliant solution, the parameter + + pos + + is declared as + + size_t + + , which ensures that the comparison expression will fail whenย a large, positive value (converted from a negative argument) is given. +

    + + #include <vector> void insert_in_table(std::vector<int> &table, std::size_t pos, int value) { if (pos >= table.size()) { @@ -80,20 +192,75 @@ void insert_in_table(std::vector<int> &table, std::size_t pos, int val } table[pos] = value; } - +
    -

    In this compliant solution, access to the vector is accomplished with the at() method. This method provides bounds checking, throwing a std::out_of_range exception if pos is not a valid index value. The insert_in_table() function is declared with noexcept(false) in compliance with ERR55-CPP. Honor exception specifications.

    - #include <vector> +

    + In this compliant solution, access to the vector is accomplished with the + + at() + + method. This method provides bounds checking, throwing a + + std::out_of_range + + exception if + + pos + + is not a valid index value. The + + insert_in_table() + + function is declared with + + noexcept(false) + + in compliance with + + ERR55-CPP. Honor exception specifications + + . +

    + + #include <vector> void insert_in_table(std::vector<int> &table, std::size_t pos, int value) noexcept(false) { table.at(pos) = value; -} +} +
    -

    In this noncompliant code example, the f_imp() function is given the (correct) ending iterator e for a container, and b is an iterator from the same container. However, it is possible that b is not within the valid range of its container. For instance, if the container were empty, b would equal e and be improperly dereferenced.

    - #include <iterator> - +

    + In this noncompliant code example, the + + f_imp() + + function is given the (correct) ending iterator + + e + + for a container, and + + b + + is an iterator from the same container. However,ย it is possible that + + b + + is notย within the valid range of its container. For instance, if the container were empty, + + b + + would equal + + e + + andย be improperly dereferenced. +

    + + #include <iterator> +ย  template <typename ForwardIterator> void f_imp(ForwardIterator b, ForwardIterator e, int val, std::forward_iterator_tag) { do { @@ -105,11 +272,18 @@ template <typename ForwardIterator> void f(ForwardIterator b, ForwardIterator e, int val) { typename std::iterator_traits<ForwardIterator>::iterator_category cat; f_imp(b, e, val, cat); -} +} +
    -

    This compliant solution tests for iterator validity before attempting to dereference b.

    - #include <iterator> +

    + This compliant solution tests for iterator validity before attempting to dereference + + b. + +

    + + #include <iterator> template <typename ForwardIterator> void f_imp(ForwardIterator b, ForwardIterator e, int val, std::forward_iterator_tag) { @@ -122,10 +296,17 @@ template <typename ForwardIterator> void f(ForwardIterator b, ForwardIterator e, int val) { typename std::iterator_traits<ForwardIterator>::iterator_category cat; f_imp(b, e, val, cat); -} +} +
    -

    Using an invalid array or container index can result in an arbitrary memory overwrite or abnormal program termination.

    +

    + Using an invalid array or container index can result in an arbitrary memory overwrite or + + abnormal program termination + + . +

    @@ -162,10 +343,14 @@ void f(ForwardIterator b, ForwardIterator e, int val) { High @@ -198,7 +383,9 @@ void f(ForwardIterator b, ForwardIterator e, int val) { 20.10 @@ -210,13 +397,24 @@ void f(ForwardIterator b, ForwardIterator e, int val) { @@ -253,14 +453,46 @@ void f(ForwardIterator b, ForwardIterator e, int val) { 2021.4 @@ -274,7 +506,9 @@ void f(ForwardIterator b, ForwardIterator e, int val) { @@ -326,7 +562,9 @@ void f(ForwardIterator b, ForwardIterator e, int val) { 4.4 @@ -338,10 +576,14 @@ void f(ForwardIterator b, ForwardIterator e, int val) { @@ -350,7 +592,17 @@ void f(ForwardIterator b, ForwardIterator e, int val) {
    - P9 + + P9 + - L2 + + L2 +
    - overflow_upon_dereference + + overflow_upon_dereference + - 6.2p0 + 6.1p0 - LANG.MEM.BOLANG.MEM.BULANG.MEM.TOLANG.MEM.TU - LANG.MEM.TBA - LANG.STRUCT.PBB - LANG.STRUCT.PPE + + LANG.MEM.BO + LANG.MEM.BU + LANG.MEM.TO + LANG.MEM.TU + + + LANG.MEM.TBA + + + LANG.STRUCT.PBB + + + LANG.STRUCT.PPE + Buffer overrun @@ -238,7 +436,9 @@ void f(ForwardIterator b, ForwardIterator e, int val) { 2021.2 - C++2891, C++3139, C++3140 + + C++2891, C++3139, C++3140 + - ABV.ANY_SIZE_ARRAY - ABV.GENERAL - ABV.STACK - ABV.TAINTED - SV.TAINTED.ALLOC_SIZE - SV.TAINTED.CALL.INDEX_ACCESS - SV.TAINTED.CALL.LOOP_BOUND - SV.TAINTED.INDEX_ACCESS + + + ABV.ANY_SIZE_ARRAY + + + + + ABV.GENERAL + + + + + ABV.STACK + + + + + ABV.TAINTED + + + + + SV.TAINTED.ALLOC_SIZE + + + + + SV.TAINTED.CALL.INDEX_ACCESS + + + + + SV.TAINTED.CALL.LOOP_BOUND + + + + + SV.TAINTED.INDEX_ACCESS + + - 45 D, 47 S, 476 S, 489 S, 64 X, 66 X, 68 X, 69 X, 70 X, 71 X, 79 X + + 45 D, 47 S, 476 S, 489 S, 64 X, 66 X, 68 X, 69 X, 70 X, 71 X, 79 X + Partially implemented @@ -290,7 +524,9 @@ void f(ForwardIterator b, ForwardIterator e, int val) { 2021.2 - CERT_CPP-CTR50-a + + CERT_CPP-CTR50-a + Guarantee that container indices are within the valid range @@ -312,7 +548,7 @@ void f(ForwardIterator b, ForwardIterator e, int val) { Checks for: - Array access out of boundsrray access out of bounds, array access with tainted indexrray access with tainted index, pointer dereference with tainted offsetointer dereference with tainted offset. + Array access out of bounds, array access with tainted index, pointer dereference with tainted offset. Rule partially covered.
    - 2891, 3139, 3140 + + 2891, 3139, 3140 + - 7.17 + 7.16 - V781 + + + V781 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess-standard.qhelp b/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess-standard.qhelp index 5c6dfc87ba..601c5aff51 100644 --- a/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess-standard.qhelp +++ b/cpp/cert/src/rules/CTR51-CPP/UsesValidContainerElementAccess-standard.qhelp @@ -1,13 +1,44 @@
    -

    Iterators are a generalization of pointers that allow a C++ program to work with different data structures (containers) in a uniform manner [ISO/IEC 14882-2014]. Pointers, references, and iterators share a close relationship in which it is required that referencing values be done through a valid iterator, pointer, or reference. Storing an iterator, reference, or pointer to an element within a container for any length of time comes with a risk that the underlying container may be modified such that the stored iterator, pointer, or reference becomes invalid. For instance, when a sequence container such as std::vector requires an underlying reallocation, outstanding iterators, pointers, and references will be invalidated [Kalev 99]. Use only a valid pointer, reference, or iterator to refer to an element of a container.

    -

    The C++ Standard, [container.requirements.general], paragraph 12 [ISO/IEC 14882-2014] states the following:

    +

    + Iterators are a generalization of pointers that allow a C++ย program to work with different data structuresย (containers) in a uniform manner [ + + ISO/IEC 14882-2014 + + ]. Pointers, references, and iterators share a close relationship in which it is required that referencing values be done through a valid iterator, pointer, or reference. Storing an iterator, reference, or pointer to an element within a container for any length of time comes with a risk that the underlying container may be modified such that the stored iterator, pointer, or reference becomes invalid. For instance, when a sequence container such as + + std::vector + + requires an underlying reallocation, outstanding iterators, pointers, and references will be invalidated [ + + Kalev 99 + + ]. Use only a + + valid pointer + + , reference, or iterator to refer to an element of a container. +

    +

    + The C++ Standard,ย [container.requirements.general], paragraph 12 + [ + + ISO/IEC 14882-2014 + + ] states the following: +

    -

    Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container.

    +

    + Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking aย container member function or passing a container as an argument to a library function shall not invalidateย iterators to, or change the values of, objects within that container. +

    -

    The C++ Standard allows references and pointers to be invalidated independently for the same operation, which may result in an invalidated reference but not an invalidated pointer. However, relying on this distinction is insecure because the object pointed to by the pointer may be different than expected even if the pointer is valid. For instance, it is possible to retrieve a pointer to an element from a container, erase that element (invalidating references when destroying the underlying object), then insert a new element at the same location within the container causing the extant pointer to now point to a valid, but distinct object. Thus, any operation that invalidates a pointer or a reference should be treated as though it invalidates both pointers and references.

    -

    The following container functions can invalidate iterators, references, and pointers under certain circumstances.

    +

    + The C++ Standard allows references and pointers to be invalidated independently for the same operation, which may result in an invalidated reference but not an invalidated pointer. However, relying on this distinction is insecure because the object pointed to by the pointer may be different than expected even if the pointer is valid. For instance, it is possible to retrieve a pointer to an element from a container, erase that element (invalidating references when destroying the underlying object), then insert a new element at the same location within the container causing the extant pointer to now point to a valid, but distinct object. Thus, any operation that invalidates a pointer or a reference should be treated as though it invalidates both pointers and references. +

    +

    + The following container functions can invalidate iterators, references, and pointers under certain circumstances. +

    @@ -29,7 +60,9 @@ @@ -44,17 +77,29 @@ @@ -121,11 +176,17 @@ @@ -142,9 +205,13 @@ @@ -193,19 +264,33 @@ @@ -254,7 +343,9 @@ @@ -278,13 +377,21 @@ @@ -360,9 +483,13 @@ @@ -397,9 +532,13 @@ @@ -503,23 +660,60 @@
    - std::deque + + std::deque + - insert() + + insert() + , - emplace_front() + + emplace_front() + , - emplace_back() + + emplace_back() + , - emplace() + + emplace() + , - push_front() + + push_front() + , - push_back() + + push_back() + X @@ -71,11 +116,17 @@ - erase() + + erase() + , - pop_back() + + pop_back() + , - resize() + + resize() + X @@ -92,7 +143,9 @@ - clear() + + clear() + X @@ -106,7 +159,9 @@
    - std::forward_list + + std::forward_list + - erase_after() + + erase_after() + , - pop_front() + + pop_front() + , - resize() + + resize() + X @@ -134,7 +195,9 @@ X - erase_after + + erase_after + shall invalidate only iterators and references to the erased elements. ([forwardlist.modifiers], paragraph 1)
    - remove() + + remove() + , - unique() + + unique() + X @@ -160,7 +227,9 @@ - clear() + + clear() + X @@ -178,7 +247,9 @@
    - std::list + + std::list + - erase() + + erase() + , - pop_front() + + pop_front() + , - pop_back() + + pop_back() + , - clear() + + clear() + , - remove() + + remove() + , - remove_if() + + remove_if() + , - unique() + + unique() + X @@ -221,7 +306,9 @@ - clear() + + clear() + X @@ -239,7 +326,9 @@
    - std::vector + + std::vector + - reserve() + + reserve() + X @@ -264,13 +355,21 @@ After - reserve() + + reserve() + , - capacity() + + capacity() + is greater or equal to the argument of - reserve + + reserve + if reallocation happens and is equal to the previous value of - capacity() + + capacity() + otherwise. Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. ([vector.capacity], paragraph 3 & paragraph 6)
    - insert() + + insert() + , - emplace_back() + + emplace_back() + , - emplace() + + emplace() + , - push_back() + + push_back() + X @@ -300,11 +407,17 @@ - erase() + + erase() + , - pop_back() + + pop_back() + , - resize() + + resize() + X @@ -321,7 +434,9 @@ - clear() + + clear() + X @@ -339,13 +454,21 @@
    - std::set + + std::set + , - std::multiset + + std::multiset + , - std::map + + std::map + , - std::multimap + + std::multimap + - erase() + + erase() + , - clear() + + clear() + X @@ -376,13 +503,21 @@
    - std::unordered_set + + std::unordered_set + , - std::unordered_multiset + + std::unordered_multiset + , - std::unordered_map + + std::unordered_map + , - std::unordered_multimap + + std::unordered_multimap + - erase() + + erase() + , - clear() + + clear() + X @@ -415,9 +554,13 @@ - insert() + + insert() + , - emplace() + + emplace() + X @@ -426,9 +569,13 @@ The - insert + + insert + and - emplace + + emplace + members shall not affect the validity of iterators if ( N @@ -450,7 +597,9 @@ N is the number of elements in the container prior to the - insert + + insert + operation, n @@ -471,9 +620,13 @@ - rehash() + + rehash() + , - reserve() + + reserve() + X @@ -487,10 +640,14 @@
    - std::valarray + + std::valarray + - resize() + + resize() +
    -

    A std::basic_string object is also a container to which this rule applies. For more specific information pertaining to std::basic_string containers, see STR52-CPP. Use valid references, pointers, and iterators to reference elements of a basic_string.

    +

    + A + + std::basic_string + + object is also a container to which this rule applies. For more specific information pertaining to + + std::basic_string + + containers, see + + STR52-CPP. Use valid references, pointers, and iterators to reference elements of a basic_string + + . +

    -

    In this noncompliant code example, pos is invalidated after the first call to insert(), and subsequent loop iterations have undefined behavior.

    - #include <deque> - +

    + In this noncompliant code example, + + pos + + is invalidated after the first call to + + insert() + + , and subsequent loop iterations have + + undefined behavior + + . +

    + + #include <deque> +ย  void f(const double *items, std::size_t count) { std::deque<double> d; auto pos = d.begin(); for (std::size_t i = 0; i < count; ++i, ++pos) { d.insert(pos, items[i] + 41.0); } -} +} +
    -

    In this compliant solution, pos is assigned a valid iterator on each insertion, preventing undefined behavior.

    - #include <deque> +

    + In this compliant solution, + + pos + + is assigned a valid iterator on each insertion, preventingย undefined behavior. +

    + + #include <deque> void f(const double *items, std::size_t count) { std::deque<double> d; @@ -528,11 +722,30 @@ void f(const double *items, std::size_t count) { pos = d.insert(pos, items[i] + 41.0); } } - +
    -

    This compliant solution replaces the handwritten loop with the generic standard template library algorithm std::transform(). The call to std::transform() accepts the range of elements to transform, the location to store the transformed values (which, in this case, is a std::inserter object to insert them at the beginning of d), and the transformation function to apply (which, in this case, is a simple lambda).

    - #include <algorithm> +

    + This compliant solution replaces the handwritten loop with the generic standard template library algorithm + + std::transform() + + . The call to + + std::transform() + + accepts the range of elements to transform, the location to store the transformed values (which, in this case, is a + + std::inserter + + object to insert them at the beginning of + + d + + ), and the transformation function to apply (which, in this case, is a simple lambda). +

    + + #include <algorithm> #include <deque> #include <iterator> @@ -541,10 +754,12 @@ void f(const double *items, std::size_t count) { std::transform(items, items + count, std::inserter(d, d.begin()), [](double d) { return d + 41.0; }); } - +
    -

    Using invalid references, pointers, or iterators to reference elements of a container results in undefined behavior.

    +

    + Using invalid references, pointers, or iterators to reference elements of a container results in undefined behavior. +

    @@ -581,10 +796,14 @@ void f(const double *items, std::size_t count) { High @@ -617,25 +836,11 @@ void f(const double *items, std::size_t count) { 20.10 - - - - - - @@ -648,7 +853,9 @@ void f(const double *items, std::size_t count) { 2021.2 @@ -663,7 +870,9 @@ void f(const double *items, std::size_t count) { 2021.4 @@ -678,7 +887,9 @@ void f(const double *items, std::size_t count) { 2021.2 @@ -703,7 +918,17 @@ void f(const double *items, std::size_t count) {
    - P6 + + P6 + - L2 + + L2 +
    - overflow_upon_dereference - -
    - - CodeSonar - - - 6.2p0 - - ALLOC.UAF + + overflow_upon_dereference + - Use After Free
    - C++4746, C++4747, C++4748, C++4749 + + C++4746, C++4747, C++4748, C++4749 + - ITER.CONTAINER.MODIFIED + + ITER.CONTAINER.MODIFIED + - CERT_CPP-CTR51-a + + CERT_CPP-CTR51-a + Do not modify container while iterating over it @@ -691,10 +902,14 @@ void f(const double *items, std::size_t count) { - 7.17 + 7.16 - V783 + + + V783 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow-standard.qhelp b/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow-standard.qhelp index a7b546f675..a5a74acb4c 100644 --- a/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow-standard.qhelp +++ b/cpp/cert/src/rules/CTR52-CPP/GuaranteeGenericCppLibraryFunctionsDoNotOverflow-standard.qhelp @@ -1,13 +1,81 @@
    -

    Copying data into a container that is not large enough to hold that data results in a buffer overflow. To prevent such errors, data copied to the destination container must be restricted on the basis of the destination container's size, or preferably, the destination container must be guaranteed to be large enough to hold the data to be copied.

    -

    Vulnerabilities that result from copying data to an undersized buffer can also involve null-terminated strings. Consult STR50-CPP. Guarantee that storage for strings has sufficient space for character data and the null terminator for specific examples of this rule that involve strings.

    -

    Copies can be made with the std::memcpy() function. However, the std::memmove() and std::memset() functions can also have the same vulnerabilities because they overwrite a block of memory without checking that the block is valid. Such issues are not limited to C standard library functions; standard template library (STL) generic algorithms, such as std::copy(), std::fill(), and std::transform(), also assume valid output buffer sizes [ISO/IEC 14882-2014].

    +

    + Copying data into a container that is not large enough to hold that data results in a buffer overflow. To prevent such errors, data copied to the destination container must be restricted on the basis of the destination container's size, or preferably, the destination container must be guaranteed to be large enough to hold the data to be copied. +

    +

    + + Vulnerabilities + + that result from copying data to an undersized buffer can also involve null-terminated strings. Consult + + STR50-CPP. Guarantee that storage for strings has sufficient space for character data and the null terminator + + for specific examples of this rule that involve strings. +

    +

    + Copies can be made with the + + std::memcpy() + + function. However, the + + std::memmove() + + and + + std::memset() + + functions can also have the same vulnerabilities because they overwrite a block of memory without checking that the block is valid. Such issues are not limited to C standard library functions; standard template library (STL) generic algorithms, such as + + std::copy() + + , + + std::fill() + + , and + + std::transform() + + , also assume valid output buffer sizes [ + + ISO/IEC 14882-2014 + + ]. +

    -

    STL containers can be subject to the same vulnerabilities as array data types. The std::copy() algorithm provides no inherent bounds checking and can lead to a buffer overflow. In this noncompliant code example, a vector of integers is copied from src to dest using std::copy(). Because std::copy() does nothing to expand the dest vector, the program will overflow the buffer on copying the first element.

    - #include <algorithm> +

    + STL containers can be subject to the same vulnerabilities as array data types. The + + std::copy() + + algorithm provides no inherent bounds checking and can lead to a buffer overflow. In this noncompliant code example, a vector of integers is copied from + + src + + to + + dest + + using + + std::copy() + + . Because + + std::copy() + + does nothing to expand the + + dest + + vector, the program will overflow the buffer on copying the first element. +

    + + #include <algorithm> #include <vector> void f(const std::vector<int> &src) { @@ -15,12 +83,21 @@ void f(const std::vector<int> &src) { std::copy(src.begin(), src.end(), dest.begin()); // ... } - -

    This hazard applies to any algorithm that takes a destination iterator, expecting to fill it with values. Most of the STL algorithms expect the destination container to have sufficient space to hold the values provided.

    +
    +

    + This hazard applies to any algorithm that takes a destination iterator, expecting to fill it with values. Most of the STL algorithms expect the destination container to have sufficient space to hold the values provided. +

    -

    The proper way to use std::copy() is to ensure the destination container can hold all the elements being copied to it. This compliant solution enlarges the capacity of the vector prior to the copy operation.

    - #include <algorithm> +

    + The proper way to use + + std::copy() + + is to ensure the destination container can hold all the elements being copied to it. This compliant solution enlarges the capacity of the vector prior to the copy operation. +

    + + #include <algorithm> #include <vector> void f(const std::vector<int> &src) { // Initialize dest with src.size() default-inserted elements @@ -28,11 +105,18 @@ void f(const std::vector<int> &src) { std::copy(src.begin(), src.end(), dest.begin()); // ... } - +
    -

    An alternative approach is to supply a std::back_insert_iterator as the destination argument. This iterator expands the destination container by one element for each element supplied by the algorithm, which guarantees the destination container will become sufficiently large to hold the elements provided.

    - #include <algorithm> +

    + An alternative approach is to supply a + + std::back_insert_iterator + + as the destination argument. This iterator expands the destination container by one element for each element supplied by the algorithm, which guarantees the destination container will become sufficiently large to hold the elements provided. +

    + + #include <algorithm> #include <iterator> #include <vector> @@ -40,49 +124,106 @@ void f(const std::vector<int> &src) { std::vector<int> dest; std::copy(src.begin(), src.end(), std::back_inserter(dest)); // ... -} +} +
    -

    The simplest solution is to construct dest from src directly, as in this compliant solution.

    - #include <vector> +

    + The simplest solution is to construct + + dest + + from + + src + + directly, as in this compliant solution. +

    + + #include <vector> void f(const std::vector<int> &src) { std::vector<int> dest(src); // ... -} +} +
    -

    In this noncompliant code example, std::fill_n() is used to fill a buffer with 10 instances of the value 0x42. However, the buffer has not allocated any space for the elements, so this operation results in a buffer overflow.

    - #include <algorithm> +

    + In this noncompliant code example, + + std::fill_n() + + is used to fill a buffer with 10ย instances of the value + + 0x42 + + . However, the buffer has not allocated any space for the elements, so this operation results in a buffer overflow. +

    + + #include <algorithm> #include <vector> void f() { std::vector<int> v; std::fill_n(v.begin(), 10, 0x42); -} +} +
    -

    This compliant solution ensures the capacity of the vector is sufficient before attempting to fill the container.

    - #include <algorithm> +

    + This compliant solution ensures the capacity of the vector is sufficient before attempting to fill the container. +

    + + #include <algorithm> #include <vector> void f() { std::vector<int> v(10); std::fill_n(v.begin(), 10, 0x42); -} -

    However, this compliant solution is inefficient. The constructor will default-construct 10 elements of type int, which are subsequently replaced by the call to std::fill_n(), meaning that each element in the container is initialized twice.

    +} +
    +

    + However, this compliant solution is inefficient. The constructor willย default-construct 10 elements of type + + int + + , which are subsequently replaced by the call to + + std::fill_n() + + , meaning that each element in the container is initialized twice. +

    -

    This compliant solution initializes v to 10 elements whose values are all 0x42.

    - #include <algorithm> +

    + This compliant solution initializes + + v + + to 10 elements whose values are all + + 0x42 + + . +

    + + #include <algorithm> #include <vector> void f() { std::vector<int> v(10, 0x42); -} +} +
    -

    Copying data to a buffer that is too small to hold the data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code.

    +

    + Copying data to a buffer that is too small to hold the data results in a buffer overflow. Attackers can + + exploit + + this condition to execute arbitrary code. +

    @@ -119,10 +260,14 @@ void f() { Medium @@ -155,7 +300,9 @@ void f() { 20.10 @@ -167,11 +314,15 @@ void f() { @@ -203,7 +356,9 @@ void f() { 2021.2
    - P18 + + P18 + - L1 + + L1 +
    - invalid_pointer_dereference + + invalid_pointer_dereference + - 6.2p0 + 6.1p0 - BADFUNC.BO.* - LANG.MEM.BO + + BADFUNC.BO.* + + + LANG.MEM.BO + A collection of warning classes that report uses of library functions prone to internal buffer overflows. @@ -188,7 +339,9 @@ void f() { 2021.2 - C++3526, C++3527, C++3528, C++3529, C++3530, C++3531, C++3532, C++3533, C++3534 + + C++3526, C++3527, C++3528, C++3529, C++3530, C++3531, C++3532, C++3533, C++3534 + - CERT_CPP-CTR52-a + + CERT_CPP-CTR52-a + Do not pass empty container iterators to std algorithms as destinations @@ -213,7 +368,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges-standard.qhelp b/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges-standard.qhelp index fbed267755..0746b4a421 100644 --- a/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges-standard.qhelp +++ b/cpp/cert/src/rules/CTR53-CPP/UseValidIteratorRanges-standard.qhelp @@ -1,61 +1,130 @@
    -

    When iterating over elements of a container, the iterators used must iterate over a valid range. An iterator range is a pair of iterators that refer to the first and past-the-end elements of the range respectively.

    -

    A valid iterator range has all of the following characteristics:

    +

    + When iterating over elements of a container, the iterators used must iterate over a valid range.ย An iterator range is a pair of iteratorsย that refer to the first and past-the-endย elements of the range respectively. +

    +

    + A valid iterator range has all of the following characteristics: +

    -

    An empty iterator range (where the two iterators are valid and equivalent) is considered to be valid.

    -

    Using a range of two iterators that are invalidated or do not refer into the same container results in undefined behavior.

    +

    + An empty iterator range (where the two iterators are valid and equivalent) is considered to be valid. +

    +

    + Using a range of two iterators that are invalidated or do not refer into the same container results in + + undefined behavior + + . +

    -

    In this noncompliant example, the two iterators that delimit the range point into the same container, but the first iterator does not precede the second. On each iteration of its internal loop, std::for_each() compares the first iterator (after incrementing it) with the second for equality; as long as they are not equal, it will continue to increment the first iterator. Incrementing the iterator representing the past-the-end element of the range results in undefined behavior.

    - #include <algorithm> +

    + In this noncompliant example, the two iterators that delimit the range point into the same container, but the first iterator does not precede the second.ย On each iteration of its internal loop, + + std::for_each() + + compares the first iterator (after incrementing it) with the second for equality;ย as long as they are not equal, it will continue to increment the first iterator. Incrementing the iterator representing the past-the-end element of the range results in + + undefined behavior + + . +

    + + #include <algorithm> #include <iostream> #include <vector> - +ย  void f(const std::vector<int> &c) { std::for_each(c.end(), c.begin(), [](int i) { std::cout << i; }); -} -

    Invalid iterator ranges can also result from comparison functions that return true for equal values. See CTR57-CPP. Provide a valid ordering predicate for more information about comparators.

    +} +
    +

    + Invalid iterator ranges can also result from comparison functions that return true for equal values. See + + CTR57-CPP. Provide a valid ordering predicate + + for more information about comparators. +

    -

    In this compliant solution, the iterator values passed to std::for_each() are passed in the proper order.

    - #include <algorithm> +

    + In this compliant solution, the iterator values passed to + + std::for_each() + + are passed in the proper order. +

    + + #include <algorithm> #include <iostream> #include <vector> void f(const std::vector<int> &c) { std::for_each(c.begin(), c.end(), [](int i) { std::cout << i; }); -} +} +
    -

    In this noncompliant code example, iterators from different containers are passed for the same iterator range. Although many STL implementations will compile this code and the program may behave as the developer expects, there is no requirement that an STL implementation treat a default-initialized iterator as a synonym for the iterator returned by end().

    - #include <algorithm> +

    + In this noncompliant code example, iterators from different containers are passed for the same iterator range. Although many STL + + implementations + + will compile this code and the program may behave as the developer expects, there is no requirement that an STL implementation treat a default-initialized iterator as a synonym for the iterator returned by + + end() + + . +

    + + #include <algorithm> #include <iostream> #include <vector> void f(const std::vector<int> &c) { std::vector<int>::const_iterator e; std::for_each(c.begin(), e, [](int i) { std::cout << i; }); -} +} +
    -

    In this compliant solution, the proper iterator generated by a call to end() is passed.

    - #include <algorithm> +

    + In this compliant solution, the properย iterator generated by a call to + + end() + + is passed. +

    + + #include <algorithm> #include <iostream> #include <vector> void f(const std::vector<int> &c) { std::for_each(c.begin(), c.end(), [](int i) { std::cout << i; }); } - +
    -

    Using an invalid iterator range is similar to allowing a buffer overflow, which can lead to an attacker running arbitrary code.

    +

    + Using an invalid iterator range is similar to allowing a buffer overflow, which can lead to an attacker running arbitrary code. +

    @@ -92,10 +161,14 @@ void f(const std::vector<int> &c) { High @@ -128,25 +201,11 @@ void f(const std::vector<int> &c) { 20.10 - - - - - - @@ -159,7 +218,9 @@ void f(const std::vector<int> &c) { 2021.2 @@ -174,8 +235,12 @@ void f(const std::vector<int> &c) { 2021.2 @@ -204,14 +271,26 @@ void f(const std::vector<int> &c) { @@ -220,8 +299,32 @@ void f(const std::vector<int> &c) {
    - P6 + + P6 + - L2 + + L2 +
    - overflow_upon_dereference - -
    - - CodeSonar - - - 6.2p0 - - LANG.MEM.BO + + overflow_upon_dereference + - Buffer Overrun
    - C++3802 + + C++3802 + - CERT_CPP-CTR53-a - CERT_CPP-CTR53-b + + CERT_CPP-CTR53-a + + + CERT_CPP-CTR53-b + Do not use an iterator range that isn't really a range @@ -192,7 +257,9 @@ void f(const std::vector<int> &c) { 4.4 - 3802 + + 3802 + - 7.17 + 7.16 - V539 + + V539 + + + , - V662 + + V662 + + + , - V789 + + + V789 + +
    -

    In Fun with erase(), Chris Rohlf discusses the exploit potential of a program that calls vector::erase() with invalid iterator ranges [Rohlf 2009].

    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + In + + Fun with erase() + + , Chris Rohlf discusses the exploit potential of a program that calls + + vector::erase() + + with invalid iterator ranges [ + + Rohlf 2009 + + ]. +

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -270,7 +373,9 @@ void f(const std::vector<int> &c) { diff --git a/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers-standard.qhelp b/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers-standard.qhelp index 98471d8e1a..404b05a8e8 100644 --- a/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers-standard.qhelp +++ b/cpp/cert/src/rules/CTR54-CPP/DoNotSubtractIteratorsForDifferentContainers-standard.qhelp @@ -1,12 +1,53 @@
    -

    When two pointers are subtracted, both must point to elements of the same array object or to one past the last element of the array object; the result is the difference of the subscripts of the two array elements. Similarly, when two iterators are subtracted (including via std::distance()), both iterators must refer to the same container object or must be obtained via a call to end() (or cend()) on the same container object.

    -

    If two unrelated iterators (including pointers) are subtracted, the operation results in undefined behavior [ISO/IEC 14882-2014]. Do not subtract two iterators (including pointers) unless both point into the same container or one past the end of the same container.

    +

    + When two pointers are subtracted, both must point to elements of the same array object or to one past the last element of the array object; the result is the difference of the subscripts of the two array elements. Similarly, when two iterators are subtracted (including via + + std::distance() + + ), both iterators must refer to the same container object or must be obtained via a call to + + end() + + (or + + cend() + + ) on the same container object. +

    +

    + If two unrelated iterators (including pointers) are subtracted, the operation results in + + undefined behavior + + [ + + ISO/IEC 14882-2014 + + ] + . Do not subtract two iterators (including pointers) unless both point into the same container or one past the end of the same container. +

    -

    This noncompliant code example attempts to determine whether the pointer test is within the range [r, r + n]. However, when test does not point within the given range, as in this example, the subtraction produces undefined behavior.

    - #include <cstddef> +

    + This noncompliant code example attempts to determine whether the + pointer + + test + + is within the range + + [r,ย r + n] + + . However, when + + test + + does not point within the given range, as in this example, the subtraction producesย undefined behavior. +

    + + #include <cstddef> #include <iostream> template <typename Ty> @@ -19,15 +60,115 @@ void f() { double *x = &foo[0]; double bar; std::cout << std::boolalpha << in_range(&bar, x, 10); -} +} +
    -

    In this noncompliant code example, the in_range() function is implemented using a comparison expression instead of subtraction. The C++ Standard, [expr.rel], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + In this noncompliant code example, the + + in_range() + + function is implemented using a comparison expression instead of subtraction. The C++ Standard,ย [expr.rel], paragraph 4 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If two operands p and q compare equal, p<=q and p>=q both yield true and p<q and p>q both yield false. Otherwise, if a pointer p compares greater than a pointer q, p>=q, p>q, q<=p, and q<p all yield true and p<=q, p<q, q>=p, and q>p all yield false. Otherwise, the result of each of the operators is unspecified.

    +

    + If two operands + + p + + and + + q + + compare equal, + + p<=q + + and + + p>=q + + both yield + + true + + and + + p<q + + and + + p>q + + both yield + + false + + . Otherwise, if a pointer + + p + + compares greater than a pointer + + q + + , + + p>=q + + , + + p>q + + , + + q<=p + + , and + + q<p + + all yield + + true + + and + + p<=q + + , + + p<q + + , + + q>=p + + , and + + q>p + + all yield + + false + + . Otherwise, the result of each of the operators is unspecified. +

    -

    Thus, comparing two pointers that do not point into the same container or one past the end of the container results in unspecified behavior. Although the following example is an improvement over the previous noncompliant code example, it does not result in portable code and may fail when executed on a segmented memory architecture (such as some antiquated x86 variants). Consequently, it is noncompliant.

    - #include <iostream> +

    + Thus, comparing two pointers that do not point into the same container or one past the end of the container results in + + unspecified behavior + + . Although the following example is an improvement over the previous noncompliant code example, it does not result in portable code and may fail when executed on a segmented memory architecture (such as some antiquated x86 variants). Consequently, it is noncompliant. +

    + + #include <iostream> template <typename Ty> bool in_range(const Ty *test, const Ty *r, size_t n) { @@ -39,11 +180,39 @@ void f() { double *x = &foo[0]; double bar; std::cout << std::boolalpha << in_range(&bar, x, 10); -} +} +
    -

    This noncompliant code example is roughly equivalent to the previous example, except that it uses iterators in place of raw pointers. As with the previous example, the in_range_impl() function exhibits unspecified behavior when the iterators do not refer into the same container because the operational semantics of a < b on a random access iterator are b - a > 0, and >= is implemented in terms of <.

    - #include <iostream> +

    + This noncompliant code example is roughly equivalent to the previous example, except that it uses iterators in place of raw pointers. As with the previous example, the + + in_range_impl() + + function exhibits + + unspecified behavior + + when the iterators do not refer into the same container because the operational semantics of + + a < b + + on a random access iterator are + + b - a > 0 + + , and + + >= + + is implemented in terms of + + < + + . +

    + + #include <iostream> #include <iterator> #include <vector> @@ -62,15 +231,95 @@ void f() { std::vector<double> foo(10); std::vector<double> bar(1); std::cout << std::boolalpha << in_range(bar.begin(), foo.begin(), foo.end()); -} +} +
    -

    In this noncompliant code example, std::less<> is used in place of the < operator. The C++ Standard, [comparisons], paragraph 14 [ISO/IEC 14882-2014], states the following:

    +

    + In this noncompliant code example, + + std::less<> + + is used in place of the + + < + + operator. The C++ Standard,ย [comparisons], paragraph 14 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.

    +

    + For templates + + greater + + , + + less + + , + + greater_equal + + , and + + less_equal + + , the specializations for any pointer typeย yield a total order, even if the built-in operators + + < + + , + + > + + , + + <= + + , + + >= + + do not. +

    -

    Although this approach yields a total ordering, the definition of that total ordering is still unspecified by the implementation. For instance, the following statement could result in the assertion triggering for a given, unrelated pair of pointers, a and b: assert(std::less<T *>()(a, b) == std::greater<T *>()(a, b));. Consequently, this noncompliant code example is still nonportable and, on common implementations of std::less<>, may even result in undefined behavior when the < operator is invoked.

    - #include <functional> +

    + Although this approach yields a total ordering, the definition of that total ordering is still unspecified by the + + implementation + + . For instance, the following statement could result in the assertion triggering for a given, unrelated pair of pointers, + + a + + and + + b + + : + + assert(std::less<T *>()(a, b) == std::greater<T *>()(a, b)); + + . Consequently, this noncompliant code example is still nonportable and, on common implementations of + + std::less<> + + , may even result in + + undefined behavior + + when the + + < + + operator is invoked. +

    + + #include <functional> #include <iostream> template <typename Ty> @@ -84,11 +333,27 @@ void f() { double *x = &foo[0]; double bar; std::cout << std::boolalpha << in_range(&bar, x, 10); -} +} +
    -

    This compliant solution demonstrates a fully portable, but likely inefficient, implementation of in_range() that compares test against each possible address in the range [r, n]. A compliant solution that is both efficient and fully portable is currently unknown.

    - #include <iostream> +

    + This compliant solution demonstrates a fully portable, but likely inefficient, implementation of + + in_range() + + that compares + + test + + against each possible address in the range + + [r,ย n] + + .ย A compliant solution that is both efficient and fully portable is currently unknown. +

    + + #include <iostream> template <typename Ty> bool in_range(const Ty *test, const Ty *r, size_t n) { @@ -110,7 +375,7 @@ void f() { double bar; std::cout << std::boolalpha << in_range(&bar, x, 10); } - +
    Item 32, "Follow Remove-Like Algorithms with - erase + + erase + If You Really Want to Remove Something"
    @@ -149,10 +414,14 @@ void f() { Medium @@ -185,27 +454,12 @@ void f() { 20.10 - - - - - - @@ -218,7 +472,9 @@ void f() { 2021.2 @@ -232,7 +488,9 @@ void f() {
    - P8 + + P8 + - L2 + + L2 +
    - invalid_pointer_subtractioninvalid_pointer_comparison - -
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.CUP - LANG.STRUCT.SUP + + invalid_pointer_subtraction + invalid_pointer_comparison + - Comparison of Unrelated Pointers - Subtraction of Unrelated Pointers
    - C++2668, C++2761, C++2762, C++2763, C++2766, C++2767, C++2768 + + C++2668, C++2761, C++2762, C++2763, C++2766, C++2767, C++2768 + - 70 S, 87 S, 437 S, 438 S + + 70 S, 87 S, 437 S, 438 S + Enhanced Enforcement @@ -248,9 +506,15 @@ void f() { 2021.2 - CERT_CPP-CTR54-a - CERT_CPP-CTR54-b - CERT_CPP-CTR54-c + + CERT_CPP-CTR54-a + + + CERT_CPP-CTR54-b + + + CERT_CPP-CTR54-c + Do not compare iterators from different containers @@ -268,7 +532,9 @@ void f() { 4.4 - 2668, 2761, 2762, 2763, 2766, 2767, 2768 + + 2668, 2761, 2762, 2763, 2766, 2767, 2768 + Enforced by QA-CPP @@ -278,7 +544,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator-standard.qhelp b/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator-standard.qhelp index cc113fc3d3..0ca34019ef 100644 --- a/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator-standard.qhelp +++ b/cpp/cert/src/rules/CTR55-CPP/DoNotUseAnAdditiveOperatorOnAnIterator-standard.qhelp @@ -1,30 +1,75 @@
    -

    Expressions that have an integral type can be added to or subtracted from a pointer, resulting in a value of the pointer type. If the resulting pointer is not a valid member of the container, or one past the last element of the container, the behavior of the additive operator is undefined. The C++ Standard, [expr.add], paragraph 5 [ISO/IEC 14882-2014], in part, states the following:

    +

    + Expressions that have an integral type can be added to or subtracted from a pointer, resulting in a value of the pointer type. If the resulting pointer is not a valid member of the container, or one past the last element of the container, the behavior of the additive operator is + + undefined + + .ย The C++ Standard, [expr.add], paragraph 5 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

    +

    + If both the pointer operand and the result point to elements of the same array object, or one pastย the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior isย undefined. +

    -

    Because iterators are a generalization of pointers, the same constraints apply to additive operators with random access iterators. Specifically, the C++ Standard, [iterator.requirements.general], paragraph 5, states the following:

    +

    + Because iterators are a generalization of pointers, the same constraints apply to additive operators with random access iterators. Specifically, the C++ Standard,ย [iterator.requirements.general], paragraph 5, states the following: +

    -

    Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. These values are called past-the-end values. Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable.

    +

    + Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last elementย of the array, so for any iterator type there is an iterator value that points past the last element of aย corresponding sequence. These values are called + + past-the-end + + values. Values of an iterator + + i + + for which theย expression + + *i + + is defined are called + + dereferenceable + + . The library never assumes that past-the-end values areย dereferenceable. +

    -

    Do not allow an expression of integral type to add to or subtract from a pointer or random access iterator when the resulting value would overflow the bounds of the container.

    +

    + Do not allow an expression of integral type to add to or subtract from a pointer or random access iterator when the resulting value would overflow the bounds of the container. +

    -

    In this noncompliant code example, a random access iterator from a std::vector is used in an additive expression, but the resulting value could be outside the bounds of the container rather than a past-the-end value.

    - #include <iostream> +

    + In this noncompliant code example, a random access iterator from a + + std::vector + + is used in an additive expression, but the resulting value could be outside the bounds of the container rather than a past-the-end value. +

    + + #include <iostream> #include <vector> - +ย  void f(const std::vector<int> &c) { for (auto i = c.begin(), e = i + 20; i != e; ++i) { std::cout << *i << std::endl; } -} +} +
    -

    This compliant solution assumes that the programmer's intention was to process up to 20 items in the container. Instead of assuming all containers will have 20 or more elements, the size of the container is used to determine the upper bound on the addition.

    - #include <algorithm> +

    + This compliant solution assumes that the programmer's intention was to process up to 20 items in the container. Instead of assuming all containers will have 20 or more elements, the size of the container is used to determine the upper bound on the addition. +

    + + #include <algorithm> #include <vector> void f(const std::vector<int> &c) { @@ -32,10 +77,21 @@ void f(const std::vector<int> &c) { for (auto i = c.begin(), e = i + std::min(maxSize, c.size()); i != e; ++i) { // ... } -} +} +
    -

    If adding or subtracting an integer to a pointer results in a reference to an element outside the array or one past the last element of the array object, the behavior is undefined but frequently leads to a buffer overflow or buffer underrun, which can often be exploited to run arbitrary code. Iterators and standard template library containers exhibit the same behavior and caveats as pointers and arrays.

    +

    + If adding or subtracting an integer to a pointer results in a reference to an element outside the array or one past the last element of the array object, the behavior is + + undefined + + but frequently leads to a buffer overflow or buffer underrun, which can often be + + exploited + + to run arbitrary code. Iterators and standard template library containers exhibit the same behavior and caveats as pointers and arrays. +

    @@ -72,10 +128,14 @@ void f(const std::vector<int> &c) { Medium @@ -108,7 +168,9 @@ void f(const std::vector<int> &c) { 2021.2 @@ -122,7 +184,9 @@ void f(const std::vector<int> &c) {
    - P18 + + P18 + - L1 + + L1 +
    - C++3526, C++3527, C++3528, C++3529, C++3530, C++3531, C++3532, C++3533, C++3534 + + C++3526, C++3527, C++3528, C++3529, C++3530, C++3531, C++3532, C++3533, C++3534 + - 567 S + + 567 S + Enhanced Enforcement @@ -138,7 +202,9 @@ void f(const std::vector<int> &c) { 2021.2 - CERT_CPP-CTR55-a + + CERT_CPP-CTR55-a + Do not add or subtract a constant with a value greater than one from an iterator @@ -148,7 +214,17 @@ void f(const std::vector<int> &c) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects-standard.qhelp b/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects-standard.qhelp index 687cd9d486..722e393d68 100644 --- a/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects-standard.qhelp +++ b/cpp/cert/src/rules/CTR56-CPP/DoNotUsePointerArithmeticOnPolymorphicObjects-standard.qhelp @@ -1,18 +1,84 @@
    -

    The definition of pointer arithmetic from the C++ Standard, [expr.add], paragraph 7 [ISO/IEC 14882-2014], states the following:

    +

    + The definition of + + pointer arithmetic + + from the C++ Standard,ย [expr.add], paragraph 7ย [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    For addition or subtraction, if the expressions P or Q have type โ€œpointer to cv Tโ€, where T is different from the cv-unqualified array element type, the behavior is undefined. [Note: In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type. โ€”end note]

    +

    + For addition or subtraction, if the expressions + + P + + or + + Q + + have type โ€œpointer to + + cv + + + T + + โ€, where + + T + + is different fromย the cv-unqualified array element type, the behavior is undefined. [ + + Note: + + In particular, a pointer to a baseย class cannot be used for pointer arithmetic when the array contains objects of a derived class type. โ€” + + endย note + + ] +

    -

    Pointer arithmetic does not account for polymorphic object sizes, and attempting to perform pointer arithmetic on a polymorphic object value results in undefined behavior.

    -

    The C++ Standard, [expr.sub], paragraph 1 [ISO/IEC 14882-2014], defines array subscripting as being identical to pointer arithmetic. Specifically, it states the following:

    +

    + Pointer arithmetic does not account for polymorphic object sizes, and attempting to perform pointer arithmetic on a polymorphic object value results in + + undefined behavior + + . +

    +

    + The C++ Standard,ย [expr.sub], paragraph 1ย [ + + ISO/IEC 14882-2014 + + ], defines array subscripting as being identical to pointer arithmetic. Specifically, it states the following: +

    -

    The expression E1[E2] is identical (by definition) to *((E1)+(E2)).

    +

    + Theย expression + + E1[E2] + + is identical (by definition) to + + *((E1)+(E2)) + + . +

    -

    Do not use pointer arithmetic, including array subscripting, on polymorphic objects.

    -

    The following code examples assume the following static variables and class definitions.

    - int globI; +

    + Do not use pointer arithmetic, including array subscripting, on polymorphic objects. +

    +

    + The following code examples assume the following static variables and class definitions. +

    + + int globI; double globD; struct S { @@ -25,12 +91,44 @@ struct T : S { double d; T() : S(), d(globD++) {} -}; +}; +
    -

    In this noncompliant code example, f() accepts an array of S objects as its first parameter. However, main() passes an array of T objects as the first argument to f(), which results in undefined behavior due to the pointer arithmetic used within the for loop.

    - #include <iostream> - +

    + In this noncompliant code example, + + f() + + accepts an array of + + S + + objects as its first parameter. However, + + main() + + passes an array of + + T + + objects as the first argument to + + f() + + , which results in + + undefined behavior + + due to the pointer arithmetic used within the + + for + + loop. +

    + + #include <iostream> +ย  // ... definitions for S, T, globI, globD ... void f(const S *someSes, std::size_t count) { @@ -43,12 +141,20 @@ int main() { T test[5]; f(test, 5); } - +
    -

    In this noncompliant code example, the for loop uses array subscripting. Since array subscripts are computed using pointer arithmetic, this code also results in undefined behavior.

    - #include <iostream> - +

    + In this noncompliant code example, the + + for + + loop uses array subscripting. Since array subscripts are computed using pointer arithmetic, this code also results in undefined behavior + . +

    + + #include <iostream> +ย  // ... definitions for S, T, globI, globD ... void f(const S *someSes, std::size_t count) { @@ -60,11 +166,15 @@ void f(const S *someSes, std::size_t count) { int main() { T test[5]; f(test, 5); -} +} +
    -

    Instead of having an array of objects, an array of pointers solves the problem of the objects being of different sizes, as in this compliant solution.

    - #include <iostream> +

    + Instead of having an array of objects, an array of pointers solves the problem of the objects being of different sizes, as in this compliant solution. +

    + + #include <iostream> // ... definitions for S, T, globI, globD ... @@ -81,12 +191,25 @@ int main() { delete v; } } - -

    The elements in the arrays are no longer polymorphic objects (instead, they are pointers to polymorphic objects), and so there is no undefined behavior with the pointer arithmetic.

    +
    +

    + The elements in the arrays are no longer polymorphic objects (instead, they are pointers to polymorphic objects), and so there is no + + undefined behavior + + with the pointer arithmetic. +

    -

    Another approach is to use a standard template library (STL) container instead of an array and have f() accept iterators as parameters, as in this compliant solution. However, because STL containers require homogeneous elements, pointers are still required within the container.

    - #include <iostream> +

    + Another approach is to use a standard templateย library (STL) container instead of an array and have + + f() + + accept iterators as parameters, as in this compliant solution. However, because STL containers require homogeneous elements, pointers are still required within the container. +

    + + #include <iostream> #include <vector> // ... definitions for S, T, globI, globD ... @@ -104,10 +227,12 @@ int main() { delete v; } } - +
    -

    Using arrays polymorphically can result in memory corruption, which could lead to an attacker being able to execute arbitrary code.

    +

    + Using arrays polymorphically can result in memory corruption, which could lead to an attacker being able to execute arbitrary code. +

    @@ -144,10 +269,14 @@ int main() { High @@ -180,7 +309,9 @@ int main() { 7.2.0 @@ -195,7 +326,9 @@ int main() { 2021.2 @@ -210,9 +343,15 @@ int main() { 2021.2 @@ -257,10 +400,14 @@ int main() { @@ -269,7 +416,17 @@ int main() {
    - P9 + + P9 + - L2 + + L2 +
    - CertC++-CTR56 + + CertC++-CTR56 + - C++3073 + + C++3073 + - CERT_CPP-CTR56-a - CERT_CPP-CTR56-b - CERT_CPP-CTR56-c + + CERT_CPP-CTR56-a + + + CERT_CPP-CTR56-b + + + CERT_CPP-CTR56-c + Don't treat arrays polymorphically @@ -229,7 +368,9 @@ int main() { - 567 S + + 567 S + Enhanced Enforcement @@ -245,7 +386,9 @@ int main() { 4.4 - 3073 + + 3073 + - 7.17 + 7.16 - V777 + + + V777 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate-standard.qhelp b/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate-standard.qhelp index 76484f51be..45e1aea530 100644 --- a/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate-standard.qhelp +++ b/cpp/cert/src/rules/CTR57-CPP/ProvideAValidOrderingPredicate-standard.qhelp @@ -1,17 +1,96 @@
    -

    Associative containers place a strict weak ordering requirement on their key comparison predicates [ISO/IEC 14882-2014]. A strict weak ordering has the following properties:

    +

    + Associative containers place a strict weak ordering requirement on their key comparison predicates + [ + + ISO/IEC 14882-2014 + + ] + . A strict weak ordering has the following properties: +

      -
    • for all x: x < x == false (irreflexivity)
    • -
    • for all x, y: if x < y then !(y < x) (asymmetry)
    • -
    • for all x, y, z: if x < y && y < z then x < z (transitivity)
    • +
    • + for all + + x + + : + + x < x == false + + (irreflexivity) +
    • +
    • + for all + + x + + , + + y + + : if + + x < y + + then + + !(y < x) + + (asymmetry) +
    • +
    • + for all + + x + + , + + y + + , + + z + + : if + + x < y && y < z + + then + + x < z + + (transitivity) +
    -

    Providing an invalid ordering predicate for an associative container (e.g., sets, maps, multisets, and multimaps), or as a comparison criterion with the sorting algorithms, can result in erratic behavior or infinite loops [Meyers 01]. When an ordering predicate is required for an associative container or a generic standard template library algorithm, the predicate must meet the requirements for inducing a strict weak ordering.

    +

    + Providing an invalid ordering predicate for an associative container (e.g., sets, maps, multisets, and multimaps), or as a comparison criterion with the sorting algorithms, can result in erratic behavior or infinite loops [ + + Meyers 01 + + ]. When an ordering predicate is required for an associative container or a generic standard template library algorithm, the predicate must meet the requirements for inducing a strict weak ordering. +

    -

    In this noncompliant code example, the std::set object is created with a comparator that does not adhere to the strict weak ordering requirement. Specifically, it fails to return false for equivalent values. As a result, the behavior of iterating over the results from std::set::equal_range results in unspecified behavior.

    - #include <functional> +

    + In this noncompliant code example, the + + std::set + + object is created with a comparator that does not adhere to the strict weak ordering requirement. Specifically, it fails to return false for equivalent values. As a result, the behavior of iterating over the results from + + std::set::equal_range + + results in + + unspecified behavior + + . +

    + + #include <functional> #include <iostream> #include <set> @@ -21,11 +100,18 @@ void f() { std::cout << *r.first << std::endl; } } - +
    -

    This compliant solution uses the default comparator with std::set instead of providing an invalid one.

    - #include <iostream> +

    + This compliant solution uses the default comparator with + + std::set + + instead of providing an invalid one. +

    + + #include <iostream> #include <set> void f() { @@ -34,11 +120,14 @@ void f() { std::cout << *r.first << std::endl; } } - +
    -

    In this noncompliant code example, the objects stored in the std::set have an overloaded operator< implementation, allowing the objects to be compared with std::less. However, the comparison operation does not provide a strict weak ordering. Specifically, two sets, x and y, whose i values are both 1, but have differing j values can result in a situation where comp(x, y) and comp(y, x) are both false, failing the asymmetry requirements.

    - #include <iostream> +

    + In this noncompliant code example, the objects stored in theย std::set have an overloadedย operator< implementation, allowing the objects to be compared withย std::less. However, the comparison operation does not provide a strict weak ordering. Specifically, two sets, x and y, whose i values are both 1, but have differing j valuesย can result in a situation whereย comp(x, y) and comp(y, x) are both false, failing the asymmetry requirements. +

    + + #include <iostream> #include <set> class S { @@ -62,17 +151,21 @@ void f() { for (auto v : t) { std::cout << v << std::endl; } -} +} +
    -

    This compliant solution uses std::tie() to properly implement the strict weak ordering operator< predicate.

    - #include <iostream> +

    + This compliant solution usesย std::tie() to properly implement the strict weak orderingย operator< predicate. +

    + + #include <iostream> #include <set> #include <tuple> - +ย  class S { int i, j; - +ย  public: S(int i, int j) : i(i), j(j) {} @@ -91,10 +184,13 @@ void f() { for (auto v : t) { std::cout << v << std::endl; } -} +} +
    -

    Using an invalid ordering rule can lead to erratic behavior or infinite loops.

    +

    + Using an invalid ordering rule can lead to erratic behavior or infinite loops. +

    @@ -131,10 +227,14 @@ void f() { High @@ -167,7 +267,9 @@ void f() { 2021.2 @@ -182,7 +284,9 @@ void f() { 2021.2
    - P2 + + P2 + - L3 + + L3 +
    - C++3293 + + C++3293 + - CERT_CPP-CTR57-a + + CERT_CPP-CTR57-a + For associative containers never use comparison function returning true for equal values @@ -192,7 +296,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable-standard.qhelp b/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable-standard.qhelp index c79d22f220..8cd1ef3b95 100644 --- a/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable-standard.qhelp +++ b/cpp/cert/src/rules/CTR58-CPP/PredicateFunctionObjectsShouldNotBeMutable-standard.qhelp @@ -1,25 +1,82 @@
    -

    The C++ standard library implements numerous common algorithms that accept a predicate function object. The C++ Standard, [algorithms.general], paragraph 10 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ standard library implements numerous common algorithms that accept a predicate function object. The C++ Standard,ย [algorithms.general], paragraph 10 + [ + + ISO/IEC 14882-2014 + + ] + , states the following: +

    -

    [Note: Unless otherwise specified, algorithms that take function objects as arguments are permitted to copy those function objects freely. Programmers for whom object identity is important should consider using a wrapper class that points to a noncopied implementation object such as reference_wrapper<T>, or some equivalent solution. โ€” end note]

    +

    + [ + + Note: + + Unless otherwise specified, algorithms that take function objects as arguments are permitted to copyย those function objects freely. Programmers for whom object identity is important should consider using aย wrapper class that points to a noncopied implementation object such as + + reference_wrapper<T> + + ,ย or some equivalent solution. โ€” + + end note + + ] +

    -

    Because it is implementation-defined whether an algorithm copies a predicate function object, any such object must either

    +

    + Because it is + + implementation-defined + + whether an algorithm copies a predicate function object, any such object must either +

      -
    • implement a function call operator that does not mutate state related to the function object's identity, such as nonstatic data members or captured values, or
    • -
    • wrap the predicate function object in a std::reference_wrapper<T> (or an equivalent solution).
    • +
    • + implement aย function call operator that does not mutate state related to the function object's identity, such as nonstatic data members or captured values, or +
    • +
    • + wrap the predicate function object in a + + std::reference_wrapper<T> + + (or an equivalent solution). +
    -

    Marking the function call operator as const is beneficial, but insufficient, because data members with the mutable storage class specifier may still be modified within a const member function.

    +

    + Marking the function call operator as + + const + + is beneficial, but insufficient, because data members with the + + mutable + + storage class specifier may still be modified within a + + const + + member function. +

    -

    This noncompliant code example attempts to remove the third item in a container using a predicate that returns true only on its third invocation.

    - #include <algorithm> +

    + This noncompliant code example attempts to remove the third item in a container using a predicate that returns + + true + + only on its third invocation. +

    + + #include <algorithm> #include <functional> #include <iostream> #include <iterator> #include <vector> - +ย ย  class MutablePredicate : public std::unary_function<int, bool> { size_t timesCalled; public: @@ -29,14 +86,14 @@ public: return ++timesCalled == 3; } }; - +ย  template <typename Iter> void print_container(Iter b, Iter e) { std::cout << "Contains: "; std::copy(b, e, std::ostream_iterator<decltype(*b)>(std::cout, " ")); std::cout << std::endl; } - +ย  void f() { std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; print_container(v.begin(), v.end()); @@ -44,28 +101,75 @@ void f() { v.erase(std::remove_if(v.begin(), v.end(), MutablePredicate()), v.end()); print_container(v.begin(), v.end()); } - -

    However, std::remove_if() is permitted to construct and use extra copies of its predicate function. Any such extra copies may result in unexpected output.

    -

    Implementation Details

    -

    This program produces the following results using gcc 4.8.1 with libstdc++.

    - Contains: 0 1 2 3 4 5 6 7 8 9 -Contains: 0 1 3 4 6 7 8 9 -

    This result arises because std::remove_if makes two copies of the predicate before invoking it. The first copy is used to determine the location of the first element in the sequence for which the predicate returns true. The subsequent copy is used for removing other elements in the sequence. This results in the third element (2) and sixth element (5) being removed; two distinct predicate functions are used.

    +
    +

    + However, + + std::remove_if() + + is permitted to construct and use extra copies of its predicate function. Any such extra copies may result in unexpected output. +

    +

    + + Implementation Details + +

    +

    + This program produces the following results using + + gcc + + 4.8.1 with + + libstdc++ + + . +

    + + Contains: 0 1 2 3 4 5 6 7 8 9 +Contains: 0 1 3 4 6 7 8 9 + +

    + This result arises because + + std::remove_if + + makes two copies of the predicate before invoking it. The first copy is used to determine the location of the first element in the sequence for which the predicate returns + + true + + . The subsequent copy is used for removing other elements in the sequence. This results in the third element ( + + 2 + + ) and sixth element ( + + 5 + + ) being removed; two distinct predicate functions are used. +

    -

    Similar to the functor noncompliant code example, this noncompliant code example attempts to remove the third item in a container using a predicate lambda function that returns true only on its third invocation. As with the functor, this lambda carries local state information, which it attempts to mutate within its function call operator.

    - #include <algorithm> +

    + Similar to the functor noncompliant code example, this noncompliant code example attempts to remove the third item in a container using a predicate lambda function that returns + + true + + only on its third invocation. As with the functor, this lambda carries local state information, which it attempts to mutate within its function call operator. +

    + + #include <algorithm> #include <iostream> #include <iterator> #include <vector> - +ย ย  template <typename Iter> void print_container(Iter b, Iter e) { std::cout << "Contains: "; std::copy(b, e, std::ostream_iterator<decltype(*b)>(std::cout, " ")); std::cout << std::endl; } - +ย  void f() { std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; print_container(v.begin(), v.end()); @@ -73,11 +177,23 @@ void f() { int timesCalled = 0; v.erase(std::remove_if(v.begin(), v.end(), [timesCalled](const int &) mutable { return ++timesCalled == 3; }), v.end()); print_container(v.begin(), v.end()); -} +} +
    -

    This compliant solution uses std::ref to wrap the predicate in a std::reference_wrapper<T> object, ensuring that copies of the wrapper object all refer to the same underlying predicate object.

    - #include <algorithm> +

    + This compliant solution uses + + std::ref + + to wrap the predicate in a + + std::reference_wrapper<T> + + object, ensuring that copies of the wrapper object all refer to the same underlying predicate object. +

    + + #include <algorithm> #include <functional> #include <iostream> #include <iterator> @@ -107,14 +223,28 @@ void f() { MutablePredicate mp; v.erase(std::remove_if(v.begin(), v.end(), std::ref(mp)), v.end()); print_container(v.begin(), v.end()); -} -

    The above compliant solution demonstrates using a reference wrapper over a functor object but can similarly be used with a stateful lambda. The code produces the expected results, where only the third element is removed.

    - Contains: 0 1 2 3 4 5 6 7 8 9 -Contains: 0 1 3 4 5 6 7 8 9 +} +
    +

    + The above com + pliant solution demonstrates using a reference wrapper over a functor object but can similarly be used with a stateful lambda. + The code produces the expected results, where only the third element is removed. +

    + + Contains: 0 1 2 3 4 5 6 7 8 9 +Contains: 0 1 3 4 5 6 7 8 9 +
    -

    Removing a specific element of a container does not require a predicate function but can instead simply use std::vector::erase(), as in this compliant solution.

    - #include <algorithm> +

    + Removing a specific element of a container does not require a predicate function but can instead simply use + + std::vector::erase() + + , as in this compliant solution. +

    + + #include <algorithm> #include <iostream> #include <iterator> #include <vector> @@ -131,10 +261,13 @@ void f() { print_container(v.begin(), v.end()); v.erase(v.begin() + 3); print_container(v.begin(), v.end()); -} +} +
    -

    Using a predicate function object that contains state can produce unexpected values.

    +

    + Using a predicate function object that contains state can produce unexpected values. +

    @@ -171,10 +304,14 @@ void f() { High @@ -207,7 +344,9 @@ void f() { 2021.2 @@ -222,7 +361,9 @@ void f() { 2021.2 @@ -248,7 +393,17 @@ void f() {
    - P3 + + P3 + - L3 + + L3 +
    - C++3225, C++3226, C++3227, C++3228, C++3229, C++3230, C++3231, C++3232, C++3233, C++3234 + + C++3225, C++3226, C++3227, C++3228, C++3229, C++3230, C++3231, C++3232, C++3233, C++3234 + - CERT_CPP-CTR58-a + + CERT_CPP-CTR58-a + Make predicates const pure functions @@ -238,8 +379,12 @@ void f() { 4.4 - 3225, 3226, 3227, 3228, 3229, - 3230, 3231, 3232, 3233, 3234 + + 3225,ย 3226, 3227, 3228, 3229, + + + 3230, 3231, 3232, 3233, 3234 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction-standard.qhelp b/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction-standard.qhelp index 65ac0a950c..b7802d78ed 100644 --- a/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction-standard.qhelp +++ b/cpp/cert/src/rules/DCL50-CPP/DoNotDefineACStyleVariadicFunction-standard.qhelp @@ -1,13 +1,62 @@
    -

    Functions can be defined to accept more formal arguments at the call site than are specified by the parameter declaration clause. Such functions are called variadic functions because they can accept a variable number of arguments from a caller. C++ provides two mechanisms by which a variadic function can be defined: function parameter packs and use of a C-style ellipsis as the final parameter declaration.

    -

    Variadic functions are flexible because they accept a varying number of arguments of differing types. However, they can also be hazardous. A variadic function using a C-style ellipsis (hereafter called a C-style variadic function) has no mechanisms to check the type safety of arguments being passed to the function or to check that the number of arguments being passed matches the semantics of the function definition. Consequently, a runtime call to a C-style variadic function that passes inappropriate arguments yields undefined behavior. Such undefined behavior could be exploited to run arbitrary code.

    -

    Do not define C-style variadic functions. (The declaration of a C-style variadic function that is never defined is permitted, as it is not harmful and can be useful in unevaluated contexts.)

    -

    Issues with C-style variadic functions can be avoided by using variadic functions defined with function parameter packs for situations in which a variable number of arguments should be passed to a function. Additionally, function currying can be used as a replacement to variadic functions. For example, in contrast to C's printf() family of functions, C++ output is implemented with the overloaded single-argument std::cout::operator<<() operators.

    -

    Noncompliant Code Example

    -

    This noncompliant code example uses a C-style variadic function to add a series of integers together. The function reads arguments until the value 0 is found. Calling this function without passing the value 0 as an argument (after the first two arguments) results in undefined behavior. Furthermore, passing any type other than an int also results in undefined behavior.

    - #include <cstdarg> +

    + Functions can be defined to accept more formal arguments at the call site than are specified by the parameter declaration clause. Such functions are called + + variadic + + functions because they can accept a variable number of arguments from a caller. C++ provides two mechanisms by which a variadic function can be defined: function parameter packs and use of a C-style ellipsis as the final parameter declaration. +

    +

    + Variadic functions are flexible because they accept a varying number of arguments of differing types. However, they can also be hazardous.ย A variadic function using a C-style ellipsis (hereafter called a + + C-style variadic function + + ) has no mechanisms to check the type safety of arguments being passed to the function or to check that the number of arguments being passed matches the semantics of the function definition.ย Consequently, a runtime call to a C-style variadic function that passes inappropriate arguments yields undefined behavior. Such + + undefined behavior + + could be + + exploited + + to run arbitrary code. +

    +

    + Do not define C-style variadic functions. (The declaration of a C-style variadic function that is never defined is permitted, as it is not harmful and can be useful in unevaluated contexts.) +

    +

    + Issues with C-style variadic functions can be avoided by using variadic functions defined with function parameter packs for situations in which a variable number of arguments should be passed to a function. Additionally, function currying can be used as a replacement to variadic functions. For example, in contrast to C's + + printf() + + family of functions, C++ output is implemented with the overloaded single-argument + + std::cout::operator<<() + + operators. +

    +

    + Noncompliant Code Example +

    +

    + This noncompliant code example uses a C-style variadic function to add a series of integers together. The function reads arguments until the value + + 0 + + is found. Calling this function without passing the value + + 0 + + as an argument (after the first two arguments) results in undefined behavior.ย Furthermore, passing any type other than an + + int + + also results inย undefined behavior. +

    + + #include <cstdarg> int add(int first, int second, ...) { int r = first + second; @@ -19,26 +68,54 @@ int add(int first, int second, ...) { va_end(va); return r; } - +
    -

    In this compliant solution, a variadic function using a function parameter pack is used to implement the add() function, allowing identical behavior for call sites. Unlike the C-style variadic function used in the noncompliant code example, this compliant solution does not result in undefined behavior if the list of parameters is not terminated with 0. Additionally, if any of the values passed to the function are not integers, the code is ill-formed rather than producing undefined behavior.

    - #include <type_traits> - +

    + In this compliant solution, a variadic function using a function parameter pack is used to implement the + + add() + + function, allowing identical behavior for call sites. Unlike the C-style variadic function used in the noncompliant code example, this compliant solution does not result in undefined behavior if the list of parameters is not terminated with + + 0 + + . Additionally, if any of the values passed to the function are not integers, the code is + + ill-formed + + rather than producingย undefined behavior. +

    + + #include <type_traits> +ย  template <typename Arg, typename std::enable_if<std::is_integral<Arg>::value>::type * = nullptr> int add(Arg f, Arg s) { return f + s; } - +ย  template <typename Arg, typename... Ts, typename std::enable_if<std::is_integral<Arg>::value>::type * = nullptr> int add(Arg f, Ts... rest) { return f + add(rest...); } - -

    This compliant solution makes use of std::enable_if to ensure that any nonintegral argument value results in an ill-formed program.

    +
    +

    + This compliant solution makes use of + + std::enable_if + + to ensure that any nonintegral argument value results in an ill-formed program. +

    -

    An alternative compliant solution that does not require recursive expansion of the function parameter pack instead expands the function parameter pack into a list of values as part of a braced initializer list. Since narrowing conversions are not allowed in a braced initializer list, the type safety is preserved despite the std::enable_if not involving any of the variadic arguments.

    - #include <type_traits> - +

    + An alternative compliant solution that does not require recursive expansion of the function parameter packย instead expands the function parameter pack into a list of values as part of a braced initializer list. Since narrowing conversions are not allowed in a braced initializer list, the type safety is preserved despite the + + std::enable_if + + not involving any of the variadic arguments. +

    + + #include <type_traits> +ย  template <typename Arg, typename... Ts, typename std::enable_if<std::is_integral<Arg>::value>::type * = nullptr> int add(Arg i, Arg j, Ts... all) { int values[] = { j, all... }; @@ -47,12 +124,32 @@ int add(Arg i, Arg j, Ts... all) { r += v; } return r; -} +} +
    -

    DCL50-CPP-EX1: It is permissible to define a C-style variadic function if that function also has external C language linkage. For instance, the function may be a definition used in a C library API that is implemented in C++.

    -

    DCL50-CPP-EX2: As stated in the normative text, C-style variadic functions that are declared but never defined are permitted. For example, when a function call expression appears in an unevaluated context, such as the argument in a sizeof expression, overload resolution is performed to determine the result type of the call but does not require a function definition. Some template metaprogramming techniques that employ SFINAE use variadic function declarations to implement compile-time type queries, as in the following example.

    - template <typename Ty> +

    + + DCL50-CPP-EX1: + + It is permissible to define a C-style variadic function if that function also has external C language linkage. For instance, the function may be a definition used in a C library API that is implemented in C++. +

    +

    + + DCL50-CPP-EX2 + + : As stated in the normative text, C-style variadic functions that are declared but never defined are permitted. For example, when a function call expression appears in an unevaluated context, such as the argument in a + + sizeof + + expression, overload resolution is performed to determine the result type of the call but does not require a function definition.ย Some template metaprogramming techniques that employ + + SFINAE + + use variadic function declarations to implement compile-time type queries, as in the following example. +

    + + template <typename Ty> class has_foo_function { typedef char yes[1]; typedef char no[2]; @@ -65,11 +162,68 @@ class has_foo_function { public: static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); -}; -

    In this example, the value of value is determined on the basis of which overload of test() is selected. The declaration of Inner *I allows use of the variable I within the decltype specifier, which results in a pointer of some (possibly void) type, with a default value of nullptr. However, if there is no declaration of Inner::foo(), the decltype specifier will be ill-formed, and that variant of test() will not be a candidate function for overload resolution due to SFINAE. The result is that the C-style variadic function variant of test() will be the only function in the candidate set. Both test() functions are declared but never defined because their definitions are not required for use within an unevaluated expression context.

    +}; +
    +

    + In this example, the value of + + value + + is determined on the basis of which overload of + + test() + + is selected. The declaration of + + Inner *I + + allows use of the variable + + I + + within the + + decltype + + specifier, which results in a pointer of some (possibly + + void + + ) type, with a default value of + + nullptr + + . However, if there is no declaration of + + Inner::foo() + + , the + + decltype + + specifier will be ill-formed, and that variant of + + test() + + will not be a candidate function for overload resolution due to SFINAE. The result is that the C-style variadic functionย variant of + + test() + + will be the only function in the candidate set. Both + + test() + + functions are declared but never defined because their definitions are not required for use within an unevaluated expression context. +

    -

    Incorrectly using a variadic function can result in abnormal program termination, unintended information disclosure, or execution of arbitrary code.

    +

    + Incorrectly using a variadic function can result in + + abnormal program termination + + , unintended information disclosure, or execution of arbitrary code. +

    @@ -106,10 +260,14 @@ public: Medium @@ -142,7 +300,9 @@ public: 20.10 @@ -173,11 +335,15 @@ public: 3.9 @@ -188,10 +354,12 @@ public: @@ -222,7 +392,11 @@ public: 2021.4 @@ -236,7 +410,9 @@ public: @@ -302,7 +484,9 @@ public: 20.10 @@ -327,7 +515,17 @@ public:
    - P12 + + P12 + - L1 + + L1 +
    - function-ellipsis + + function-ellipsis + Fully checked @@ -158,7 +318,9 @@ public: 7.2.0 - CertC++-DCL50 + + CertC++-DCL50 + - cert-dcl50-cpp + + cert-dcl50-cpp + Checked by - clang-tidy + + clang-tidy + .
    - 6.2p0 + 6.1p0 - LANG.STRUCT.ELLIPSIS + + LANG.STRUCT.ELLIPSIS + Ellipsis @@ -207,7 +375,9 @@ public: 2021.2 - C++2012, C++2625 + + C++2012, C++2625 + - MISRA.FUNC.VARARG + + + MISRA.FUNC.VARARG + + - 41 S + + 41 S + Fully Implemented @@ -252,7 +428,9 @@ public: 2021.2 - CERT_CPP-DCL50-a + + CERT_CPP-DCL50-a + Functions shall not be defined with a variable number of arguments @@ -286,8 +464,12 @@ public: 4.4 - 2012, - 2625 + + 2012, + + + 2625 + - function-ellipsis + + function-ellipsis + Fully checked @@ -318,7 +502,11 @@ public: 4.10 - FunctionEllipsis + + + FunctionEllipsis + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/EnumeratorReusesReservedName-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/FunctionReusesReservedName-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/ObjectReusesReservedName-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/RedefiningOfStandardLibraryName-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/ReuseOfReservedIdentifier-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfDoubleUnderscoreReservedPrefix-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfReservedLiteralSuffixIdentifier-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfReservedNamePrefix-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/UseOfReservedNamePrefix-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfReservedNamePrefix-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfReservedNamePrefix-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix-standard.qhelp b/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix-standard.qhelp index da543df152..9c074f0ea6 100644 --- a/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix-standard.qhelp +++ b/cpp/cert/src/rules/DCL51-CPP/UseOfSingleUnderscoreReservedPrefix-standard.qhelp @@ -1,60 +1,246 @@
    -

    The C++ Standard, [reserved.names] [ISO/IEC 14882-2014], specifies the following rules regarding reserved names:

    +

    + The C++ Standard,ย [reserved.names] + [ + + ISO/IEC 14882-2014 + + ] + , specifies the following rules regarding reserved names + : +

      -
    • A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
    • -
    • A translation unit shall not #define or #undef names lexically identical to keywords, to the identifiers listed in Table 3, or to the attribute-tokens described in 7.6.
    • -
    • Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
    • -
    • Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
    • -
    • Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace std and in the global namespace.
    • -
    • Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.
    • -
    • Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
    • -
    • Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.
    • -
    • For each type T from the Standard C library, the types ::T and std::T are reserved to the implementation and, when defined, ::T shall be identical to std::T.
    • -
    • Literal suffix identifiers that do not start with an underscore are reserved for future standardization.
    • +
    • + A translation unit that includes a standard library header shall not + + #define + + or + + #undef + + names declared in any standard library header. +
    • +
    • + A translation unit shall not + + #define + + or + + #undef + + names lexically identical to keywords, to the identifiers listedย in Table 3, or to the + + attribute-token + + s described in 7.6. +
    • +
    • + Each name that contains a double underscore + + __ + + or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. +
    • +
    • + Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace. +
    • +
    • + Each name declared as an object with external linkage in a header is reserved to the implementation to designate that library object with external linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage. +
    • +
    • + Each name from the Standard C library declared with external linkage is reserved to the implementation for use as a name with + + extern "C" + + linkage, both in namespace + + std + + and in the global namespace. +
    • +
    • + Each function signature from the Standard C library declared with external linkage is reserved to the implementation for use as a function signature with both + + extern "C" + + and + + extern "C++" + + linkage, or as a name of namespace scope in the global namespace. +
    • +
    • + For each type + + T + + from the Standard C library, the types + + ::T + + and + + std::T + + are reserved to the implementation and, when defined, + + ::T + + shall be identical to + + std::T + + . +
    • +
    • + Literal suffix identifiers that do not start with an underscore are reserved for future standardization. +
    -

    The identifiers and attribute names referred to in the preceding excerpt are override, final, alignas, carries_dependency, deprecated, and noreturn.

    -

    No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in undefined behavior. Do not declare or define a reserved identifier.

    +

    + The identifiers and attribute names referred to in the preceding excerpt are + + override + + , + + final + + , + + alignas + + , + + carries_dependency + + , + + deprecated + + , and + + noreturn + + . +

    +

    + No other identifiers are reserved. Declaring or defining an identifier in a context in which it is reserved results in + + undefined behavior + + . Do not declare or define a reserved identifier. +

    -

    A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included.

    - #ifndef _MY_HEADER_H_ +

    + A common practice is to use a macro in a preprocessor conditional that guards against multiple inclusions of a header file. While this is a recommended practice, many programs use reserved names as the header guards. Such a name may clash with reserved names defined by the implementation of the C++ standard template library in its headers or with reserved names implicitly predefined by the compiler even when no C++ standard library header is included. +

    + + #ifndef _MY_HEADER_H_ #define _MY_HEADER_H_ // Contents of <my_header.h> #endif // _MY_HEADER_H_ - +
    -

    This compliant solution avoids using leading or trailing underscores in the name of the header guard.

    - #ifndef MY_HEADER_H +

    + This compliant solution avoids using leading or trailing underscores in the name of the header guard. +

    + + #ifndef MY_HEADER_H #define MY_HEADER_H // Contents of <my_header.h> #endif // MY_HEADER_H - +
    -

    In this noncompliant code example, a user-defined literal operator"" x is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations.

    - #include <cstddef> - -unsigned int operator"" x(const char *, std::size_t); +

    + In this noncompliant code example, a user-defined literal + operator"" x + is declared. However, literal suffix identifiers are required to start with an underscore; literal suffixes without the underscore prefix are reserved for future library implementations. +

    + + #include <cstddef> +ย  +unsigned int operator"" x(const char *, std::size_t); +
    -

    In this compliant solution, the user-defined literal is named operator"" _x, which is not a reserved identifier.

    - #include <cstddef> - -unsigned int operator"" _x(const char *, std::size_t); -

    The name of the user-defined literal is operator"" _x and not _x, which would have otherwise been reserved for the global namespace.

    +

    + In this compliant solution, the user-defined literal is named + + operator"" _x + + , which is not a reserved identifier. +

    + + #include <cstddef> +ย  +unsigned int operator"" _x(const char *, std::size_t); + +

    + The name of the user-defined literal is + + operator"" _x + + and not + + _x + + , which would have otherwise been reserved for the global namespace. +

    -

    In this noncompliant code example, the names of the file scope objects _max_limit and _limit both begin with an underscore. Because it is static, the declaration of _max_limit might seem to be impervious to clashes with names defined by the implementation. However, because the header <cstddef> is included to define std::size_t, a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because _limit has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit.

    - #include <cstddef> // std::for size_t +

    + In this noncompliant code example, the names of the file scope objects + + _max_limit + + and + + _limit + + both begin with an underscore. Because it is + + static + + , the declaration of + + _max_limit + + might seem to be impervious to clashes with names defined by the implementation. However, because the header + + <cstddef> + + is included to define + + std::size_t + + , a potential for a name clash exists. (Note, however, that a conforming compiler may implicitly declare reserved names regardless of whether any C++ standard template library header has been explicitly included.) In addition, because + + _limit + + has external linkage, it may clash with a symbol with the same name defined in the language runtime library even if such a symbol is not declared in any header. Consequently, it is unsafe to start the name of any file scope identifier with an underscore even if its linkage limits its visibility to a single translation unit. +

    + + #include <cstddef> // std::for size_t static const std::size_t _max_limit = 1024; std::size_t _limit = 100; @@ -62,11 +248,14 @@ std::size_t _limit = 100; unsigned int get_value(unsigned int count) { return count < _limit ? count : _limit; } - +
    -

    In this compliant solution, file scope identifiers do not begin with an underscore.

    - #include <cstddef> // for size_t +

    + In this compliant solution, file scope identifiers do not begin with an underscore. +

    + + #include <cstddef> // for size_t static const std::size_t max_limit = 1024; std::size_t limit = 100; @@ -74,48 +263,100 @@ std::size_t limit = 100; unsigned int get_value(unsigned int count) { return count < limit ? count : limit; } - +
    -

    In this noncompliant code example, because the C++ standard template library header <cinttypes> is specified to include <cstdint>, as per [c.files] paragraph 4 [ISO/IEC 14882-2014], the name MAX_SIZE conflicts with the name of the <cstdint> header macro used to denote the upper limit of std:size_t.

    - #include <cinttypes> // for int_fast16_t +

    + In this noncompliant code example, because the C++ standard template library header + + <cinttypes> + + is specified to include + + <cstdint> + + , as per [c.files] paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , the name + + MAX_SIZE + + conflicts with the name of the + + <cstdint> + + header macro used to denote the upper limit of + + std:size_t. + +

    + + #include <cinttypes> // for int_fast16_t void f(std::int_fast16_t val) { enum { MAX_SIZE = 80 }; // ... } - +
    -

    This compliant solution avoids redefining reserved names.

    - #include <cinttypes> // for std::int_fast16_t +

    + This compliant solution avoids redefining reserved names. +

    + + #include <cinttypes> // for std::int_fast16_t void f(std::int_fast16_t val) { enum { BufferSize = 80 }; // ... -} +} +
    -

    DCL51-CPP-EX1: For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example.

    - // Sometimes generated by configuration tools such as autoconf +

    + + DCL51-CPP-EX1: + + For compatibility with other compiler vendors or language standard modes, it is acceptable to create a macro identifier that is the same as a reserved identifier so long as the behavior is semantically identical, as in this example. +

    + + // Sometimes generated by configuration tools such as autoconf #define const const - +ย  // Allowed compilers with semantically equivalent extension behavior -#define inline __inline -

    DCL51-CPP-EX2: As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the libc++ STL implementation.

    - // The following declaration of a reserved identifier exists in the libc++ implementation of +#define inline __inline + +

    + + DCL51-CPP-EX2: + + As a compiler vendor or standard library developer, it is acceptable to use identifiers reserved for your implementation. Reserved identifiers may be defined by the compiler, in standard library headers, or in headers included by a standard library header, as in this example declaration from the + + libc++ + + STL implementation. +

    + + // The following declaration of a reserved identifier exists in the libc++ implementation of // std::basic_string as a public member. The original source code may be found at: // http://llvm.org/svn/llvm-project/libcxx/trunk/include/string - +ย  template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string { // ... - +ย  bool __invariants() const; -}; +}; +
    -

    Using reserved identifiers can lead to incorrect program operation.

    +

    + Using reserved identifiers can lead to incorrect program operation. +

    @@ -152,10 +393,14 @@ class basic_string { Low @@ -188,7 +433,9 @@ class basic_string { 20.10 @@ -219,16 +468,26 @@ class basic_string { 3.9 @@ -240,11 +499,15 @@ class basic_string { @@ -276,12 +541,24 @@ class basic_string { 2021.4 @@ -295,7 +572,9 @@ class basic_string { @@ -367,10 +660,14 @@ class basic_string { @@ -385,7 +682,9 @@ class basic_string { 20.10 @@ -410,7 +713,17 @@ class basic_string {
    - P3 + + P3 + - L3 + + L3 +
    - reserved-identifier + + reserved-identifier + Partially checked @@ -204,7 +451,9 @@ class basic_string { 7.2.0 - CertC++-DCL51 + + CertC++-DCL51 + - -Wreserved-id-macro - -Wuser-defined-literals + + -Wreserved-id-macro + + + -Wuser-defined-literals + The - -Wreserved-id-macro + + -Wreserved-id-macro + flag is not enabled by default or with - -Wall + + -Wall + , but is enabled with - -Weverything + + -Weverything + . This flag does not catch all instances of this rule, such as redefining reserved names. - 6.2p0 + 6.1p0 - LANG.ID.NU.MK - LANG.STRUCT.DECL.RESERVED + + LANG.ID.NU.MK + + + LANG.STRUCT.DECL.RESERVED + Macro name is C keyword @@ -261,7 +524,9 @@ class basic_string { 2021.2 - C++5003 + + C++5003 + - MISRA.DEFINE.WRONGNAME - MISRA.DEFINE.WRONGNAME.UNDERSCORE - MISRA.UNDEF.WRONGNAME - MISRA.UNDEF.WRONGNAME.UNDERSCORE - MISRA.STDLIB.WRONGNAME - MISRA.STDLIB.WRONGNAME.UNDERSCORE + + MISRA.DEFINE.WRONGNAME + + + MISRA.DEFINE.WRONGNAME.UNDERSCORE + + + MISRA.UNDEF.WRONGNAME + + + MISRA.UNDEF.WRONGNAME.UNDERSCORE + + + MISRA.STDLIB.WRONGNAME + + + MISRA.STDLIB.WRONGNAME.UNDERSCORE + - 86 S, 218 S, 219 S, 580 S + + 86 S, 218 S, 219 S, 580 S + Fully implemented @@ -311,12 +590,24 @@ class basic_string { 2021.2 - CERT_CPP-DCL51-a - CERT_CPP-DCL51-b - CERT_CPP-DCL51-c - CERT_CPP-DCL51-d - CERT_CPP-DCL51-e - CERT_CPP-DCL51-f + + CERT_CPP-DCL51-a + + + CERT_CPP-DCL51-b + + + CERT_CPP-DCL51-c + + + CERT_CPP-DCL51-d + + + CERT_CPP-DCL51-e + + + CERT_CPP-DCL51-f + Do not #define or #undef identifiers with names which start with underscore @@ -355,7 +646,9 @@ class basic_string { 4.4 - 5003 + + 5003 + - 7.17 + 7.16 - V1059 + + + V1059 + + - reserved-identifier + + reserved-identifier + Partially checked @@ -401,7 +700,11 @@ class basic_string { 4.10 - 978 + + + 978 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier-standard.qhelp b/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier-standard.qhelp index 16d518d07f..669f269362 100644 --- a/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier-standard.qhelp +++ b/cpp/cert/src/rules/DCL53-CPP/LocalConstructorInitializedObjectHidesIdentifier-standard.qhelp @@ -1,19 +1,72 @@
    -

    It is possible to devise syntax that can ambiguously be interpreted as either an expression statement or a declaration. Syntax of this sort is called a vexing parse because the compiler must use disambiguation rules to determine the semantic results. The C++ Standard, [stmt.ambig], paragraph 1 [ISO/IEC 14882-2014], in part, states the following:

    +

    + It is possible to devise syntax that can ambiguously be interpreted as either an expression statement or a declaration. Syntax of this sort is called a + + vexing parse + + because the compiler must use disambiguation rules to determine the semantic results. The C++ Standard,ย [stmt.ambig], paragraph 1 [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. ...

    +

    + There is an ambiguity in the grammar involving + + expression-statement + + s and declarations: An + + expression-statement + + with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a + + ( + + . In those cases the statement is aย declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it isย an + + expression-statement + + or a declaration. ... +

    -

    A similarly vexing parse exists within the context of a declaration where syntax can be ambiguously interpreted as either a function declaration or a declaration with a function-style cast as the initializer. The C++ Standard, [dcl.ambig.res], paragraph 1, in part, states the following:

    +

    + A similarly vexing parse exists within the context of a declaration where syntax can be ambiguously interpreted as either a function declaration or a declaration with a function-style cast as the initializer. The C++ Standard,ย [dcl.ambig.res], paragraph 1, in part, states the following: +

    -

    The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration.

    +

    + The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8ย can also occur in the context of a declaration. In that context, the choice is between a function declarationย with a redundant set of parentheses around a parameter name and an object declaration with a function-styleย cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any constructย that could possibly be a declaration a declaration. +

    -

    Do not write a syntactically ambiguous declaration. With the advent of uniform initialization syntax using a braced-init-list, there is now syntax that unambiguously specifies a declaration instead of an expression statement. Declarations can also be disambiguated by using nonfunction-style casts, by initializing using =, or by removing extraneous parenthesis around the parameter name.

    +

    + Do not write a syntactically ambiguous declaration. With the advent of uniform initialization syntax using aย braced-init-list, there is now syntax that unambiguously specifies a declaration instead of an expression statement. Declarations can also be disambiguated by using nonfunction-style casts, by initializing usingย =, or by removing extraneous parenthesis around the parameter name. +

    -

    In this noncompliant code example, an anonymous local variable of type std::unique_lock is expected to lock and unlock the mutex m by virtue of RAII. However, the declaration is syntactically ambiguous as it can be interpreted as declaring an anonymous object and calling its single-argument converting constructor or interpreted as declaring an object named m and default constructing it. The syntax used in this example defines the latter instead of the former, and so the mutex object is never locked.

    - #include <mutex> +

    + In this noncompliant code example, an anonymous local variable of type + + std::unique_lock + + is expected to lock and unlock theย mutex + + m + + by virtue of + + RAII. + + However, the declaration is syntactically ambiguous as it can be interpreted as declaring an anonymous object and calling its single-argument converting constructor or interpreted as declaring an object named + + m + + and default constructing it. The syntax used in this example defines the latter instead of the former, and so the mutex object is never locked. +

    + + #include <mutex> static std::mutex m; static int shared_resource; @@ -21,24 +74,52 @@ static int shared_resource; void increment_by_42() { std::unique_lock<std::mutex>(m); shared_resource += 42; -} +} +
    -

    In this compliant solution, the lock object is given an identifier (other than m) and the proper converting constructor is called.

    - #include <mutex> - +

    + In this compliant solution, the lock object is given an identifier (other than + + m + + ) and the proper converting constructor is called. +

    + + #include <mutex> +ย  static std::mutex m; static int shared_resource; void increment_by_42() { std::unique_lock<std::mutex> lock(m); shared_resource += 42; -} +} +
    -

    In this noncompliant code example, an attempt is made to declare a local variable, w, of type Widget while executing the default constructor. However, this declaration is syntactically ambiguous where the code could be either a declaration of a function pointer accepting no arguments and returning a Widget or a declaration of a local variable of type Widget. The syntax used in this example defines the former instead of the latter.

    - #include <iostream> - +

    + In this noncompliant code example, an attempt is made to declare a local variable, + + w + + , of type + + Widget + + while executing the default constructor. However, this declaration is syntactically ambiguous where the code could be either a declaration of a function pointer accepting no arguments and returning a + + Widget + + or a declaration of a local variable of type + + Widget + + . The syntax used in this example defines the former instead of the latter. +

    + + #include <iostream> +ย  struct Widget { Widget() { std::cout << "Constructed" << std::endl; } }; @@ -46,12 +127,21 @@ struct Widget { void f() { Widget w(); } - -

    As a result, this program compiles and prints no output because the default constructor is never actually invoked.

    +
    +

    + As a result, this program compiles and prints no output because the default constructor is never actually invoked. +

    -

    This compliant solution shows two equally compliant ways to write the declaration. The first way is to elide the parentheses after the variable declaration, which ensures the syntax is that of a variable declaration instead of a function declaration. The second way is to use a braced-init-list to direct-initialize the local variable.

    - #include <iostream> +

    + This compliant solution shows two equally compliant ways to write the declaration. The first way is to elide the parentheses after the variable declaration, which ensures the syntax is that of a variable declaration instead of a function declaration. The second way is to use a + + braced-init-list + + to direct-initialize the local variable. +

    + + #include <iostream> struct Widget { Widget() { std::cout << "Constructed" << std::endl; } @@ -61,12 +151,37 @@ void f() { Widget w1; // Elide the parentheses Widget w2{}; // Use direct initialization } - -

    Running this program produces the output Constructed twice, once for w1 and once for w2.

    +
    +

    + Running this program produces the output + + Constructed + + twice, once for + + w1 + + and once for + + w2 + + . +

    -

    This noncompliant code example demonstrates a vexing parse. The declaration Gadget g(Widget(i)); is not parsed as declaring a Gadget object with a single argument. It is instead parsed as a function declaration with a redundant set of parentheses around a parameter.

    - #include <iostream> +

    + This noncompliant code example demonstrates a vexing parse. The declaration + + Gadget g(Widget(i)); + + is not parsed as declaring a + + Gadget + + object with a single argument. It is instead parsed as a function declaration with a redundant set of parentheses around a parameter. +

    + + #include <iostream> struct Widget { explicit Widget(int i) { std::cout << "Widget constructed" << std::endl; } @@ -81,15 +196,51 @@ void f() { Gadget g(Widget(i)); std::cout << i << std::endl; } - -

    Parentheses around parameter names are optional, so the following is a semantically identical spelling of the declaration.

    - Gadget g(Widget i); - -

    As a result, this program is well-formed and prints only 3 as output because no Gadget or Widget objects are constructed.

    +
    +

    + Parentheses around parameter names are optional, so the following is a semantically identical spelling of the declaration. +

    + + Gadget g(Widget i); + +

    + As a result, this program is well-formed and prints only + + 3 + + as output because no + + Gadget + + or + + Widget + + objects are constructed. +

    -

    This compliant solution demonstrates two equally compliant ways to write the declaration of g. The first declaration, g1, uses an extra set of parentheses around the argument to the constructor call, forcing the compiler to parse it as a local variable declaration of type Gadget instead of as a function declaration. The second declaration, g2, uses direct initialization to similar effect.

    - #include <iostream> +

    + This compliant solution demonstrates two equally compliant ways to write the declaration of + + g + + . The first declaration, + + g1 + + , uses an extra set of parentheses around the argument to the constructor call, forcing the compiler to parse it as a local variable declaration of type + + Gadget + + instead of as a function declaration. The second declaration, + + g2 + + , uses direct initialization to similar effect. +

    + + #include <iostream> struct Widget { explicit Widget(int i) { std::cout << "Widget constructed" << std::endl; } @@ -105,16 +256,22 @@ void f() { Gadget g2{Widget(i)}; // Use direct initialization std::cout << i << std::endl; } - -

    Running this program produces the expected output.

    - Widget constructed + +

    + Running this program produces the expected output. +

    + + Widget constructed Gadget constructed Widget constructed Gadget constructed -3 +3 +
    -

    Syntactically ambiguous declarations can lead to unexpected program execution. However, it is likely that rudimentary testing would uncover violations of this rule.

    +

    + Syntactically ambiguous declarations can lead to unexpected program execution. However, it is likely that rudimentary testing would uncover violations of this rule. +

    @@ -151,10 +308,14 @@ Gadget constructed Medium @@ -187,7 +348,9 @@ Gadget constructed 2021.2 @@ -202,7 +365,11 @@ Gadget constructed 2021.4 @@ -216,8 +383,11 @@ Gadget constructed @@ -272,7 +447,9 @@ Gadget constructed 4.4 @@ -287,7 +464,9 @@ Gadget constructed 3.9 @@ -302,7 +481,11 @@ Gadget constructed 4.10 @@ -311,7 +494,17 @@ Gadget constructed
    - P2 + + P2 + - L3 + + L3 +
    - C++2502, C++2510 + + C++2502, C++2510 + - CERT.DCL.AMBIGUOUS_DECL + + + CERT.DCL.AMBIGUOUS_DECL + + - 296 S - + + 296 S + + + Partially implemented @@ -233,8 +403,13 @@ Gadget constructed 2021.2 - CERT_CPP-DCL53-a - CERT_CPP-DCL53-bCERT_CPP-DCL53-c + + CERT_CPP-DCL53-a + + + CERT_CPP-DCL53-b + CERT_CPP-DCL53-c + Parameter names in function declarations should not be enclosed in parentheses @@ -258,7 +433,7 @@ Gadget constructed Checks for declarations that can be confused between: - Function and object declarationunction and object declaration, unnamed object or function parameter declarationnnamed object or function parameter declaration. + Function and object declaration, unnamed object or function parameter declaration. Rule fully covered.
    - 2502, 2510 + + 2502, 2510 + - -Wvexing-parse + + -Wvexing-parse + - S3468 + + + S3468 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration-standard.qhelp b/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration-standard.qhelp index 16d518d07f..669f269362 100644 --- a/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration-standard.qhelp +++ b/cpp/cert/src/rules/DCL53-CPP/LocalFunctionDeclaration-standard.qhelp @@ -1,19 +1,72 @@
    -

    It is possible to devise syntax that can ambiguously be interpreted as either an expression statement or a declaration. Syntax of this sort is called a vexing parse because the compiler must use disambiguation rules to determine the semantic results. The C++ Standard, [stmt.ambig], paragraph 1 [ISO/IEC 14882-2014], in part, states the following:

    +

    + It is possible to devise syntax that can ambiguously be interpreted as either an expression statement or a declaration. Syntax of this sort is called a + + vexing parse + + because the compiler must use disambiguation rules to determine the semantic results. The C++ Standard,ย [stmt.ambig], paragraph 1 [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. ...

    +

    + There is an ambiguity in the grammar involving + + expression-statement + + s and declarations: An + + expression-statement + + with a function-style explicit type conversion as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a + + ( + + . In those cases the statement is aย declaration. [Note: To disambiguate, the whole statement might have to be examined to determine if it isย an + + expression-statement + + or a declaration. ... +

    -

    A similarly vexing parse exists within the context of a declaration where syntax can be ambiguously interpreted as either a function declaration or a declaration with a function-style cast as the initializer. The C++ Standard, [dcl.ambig.res], paragraph 1, in part, states the following:

    +

    + A similarly vexing parse exists within the context of a declaration where syntax can be ambiguously interpreted as either a function declaration or a declaration with a function-style cast as the initializer. The C++ Standard,ย [dcl.ambig.res], paragraph 1, in part, states the following: +

    -

    The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration.

    +

    + The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8ย can also occur in the context of a declaration. In that context, the choice is between a function declarationย with a redundant set of parentheses around a parameter name and an object declaration with a function-styleย cast as the initializer. Just as for the ambiguities mentioned in 6.8, the resolution is to consider any constructย that could possibly be a declaration a declaration. +

    -

    Do not write a syntactically ambiguous declaration. With the advent of uniform initialization syntax using a braced-init-list, there is now syntax that unambiguously specifies a declaration instead of an expression statement. Declarations can also be disambiguated by using nonfunction-style casts, by initializing using =, or by removing extraneous parenthesis around the parameter name.

    +

    + Do not write a syntactically ambiguous declaration. With the advent of uniform initialization syntax using aย braced-init-list, there is now syntax that unambiguously specifies a declaration instead of an expression statement. Declarations can also be disambiguated by using nonfunction-style casts, by initializing usingย =, or by removing extraneous parenthesis around the parameter name. +

    -

    In this noncompliant code example, an anonymous local variable of type std::unique_lock is expected to lock and unlock the mutex m by virtue of RAII. However, the declaration is syntactically ambiguous as it can be interpreted as declaring an anonymous object and calling its single-argument converting constructor or interpreted as declaring an object named m and default constructing it. The syntax used in this example defines the latter instead of the former, and so the mutex object is never locked.

    - #include <mutex> +

    + In this noncompliant code example, an anonymous local variable of type + + std::unique_lock + + is expected to lock and unlock theย mutex + + m + + by virtue of + + RAII. + + However, the declaration is syntactically ambiguous as it can be interpreted as declaring an anonymous object and calling its single-argument converting constructor or interpreted as declaring an object named + + m + + and default constructing it. The syntax used in this example defines the latter instead of the former, and so the mutex object is never locked. +

    + + #include <mutex> static std::mutex m; static int shared_resource; @@ -21,24 +74,52 @@ static int shared_resource; void increment_by_42() { std::unique_lock<std::mutex>(m); shared_resource += 42; -} +} +
    -

    In this compliant solution, the lock object is given an identifier (other than m) and the proper converting constructor is called.

    - #include <mutex> - +

    + In this compliant solution, the lock object is given an identifier (other than + + m + + ) and the proper converting constructor is called. +

    + + #include <mutex> +ย  static std::mutex m; static int shared_resource; void increment_by_42() { std::unique_lock<std::mutex> lock(m); shared_resource += 42; -} +} +
    -

    In this noncompliant code example, an attempt is made to declare a local variable, w, of type Widget while executing the default constructor. However, this declaration is syntactically ambiguous where the code could be either a declaration of a function pointer accepting no arguments and returning a Widget or a declaration of a local variable of type Widget. The syntax used in this example defines the former instead of the latter.

    - #include <iostream> - +

    + In this noncompliant code example, an attempt is made to declare a local variable, + + w + + , of type + + Widget + + while executing the default constructor. However, this declaration is syntactically ambiguous where the code could be either a declaration of a function pointer accepting no arguments and returning a + + Widget + + or a declaration of a local variable of type + + Widget + + . The syntax used in this example defines the former instead of the latter. +

    + + #include <iostream> +ย  struct Widget { Widget() { std::cout << "Constructed" << std::endl; } }; @@ -46,12 +127,21 @@ struct Widget { void f() { Widget w(); } - -

    As a result, this program compiles and prints no output because the default constructor is never actually invoked.

    +
    +

    + As a result, this program compiles and prints no output because the default constructor is never actually invoked. +

    -

    This compliant solution shows two equally compliant ways to write the declaration. The first way is to elide the parentheses after the variable declaration, which ensures the syntax is that of a variable declaration instead of a function declaration. The second way is to use a braced-init-list to direct-initialize the local variable.

    - #include <iostream> +

    + This compliant solution shows two equally compliant ways to write the declaration. The first way is to elide the parentheses after the variable declaration, which ensures the syntax is that of a variable declaration instead of a function declaration. The second way is to use a + + braced-init-list + + to direct-initialize the local variable. +

    + + #include <iostream> struct Widget { Widget() { std::cout << "Constructed" << std::endl; } @@ -61,12 +151,37 @@ void f() { Widget w1; // Elide the parentheses Widget w2{}; // Use direct initialization } - -

    Running this program produces the output Constructed twice, once for w1 and once for w2.

    +
    +

    + Running this program produces the output + + Constructed + + twice, once for + + w1 + + and once for + + w2 + + . +

    -

    This noncompliant code example demonstrates a vexing parse. The declaration Gadget g(Widget(i)); is not parsed as declaring a Gadget object with a single argument. It is instead parsed as a function declaration with a redundant set of parentheses around a parameter.

    - #include <iostream> +

    + This noncompliant code example demonstrates a vexing parse. The declaration + + Gadget g(Widget(i)); + + is not parsed as declaring a + + Gadget + + object with a single argument. It is instead parsed as a function declaration with a redundant set of parentheses around a parameter. +

    + + #include <iostream> struct Widget { explicit Widget(int i) { std::cout << "Widget constructed" << std::endl; } @@ -81,15 +196,51 @@ void f() { Gadget g(Widget(i)); std::cout << i << std::endl; } - -

    Parentheses around parameter names are optional, so the following is a semantically identical spelling of the declaration.

    - Gadget g(Widget i); - -

    As a result, this program is well-formed and prints only 3 as output because no Gadget or Widget objects are constructed.

    +
    +

    + Parentheses around parameter names are optional, so the following is a semantically identical spelling of the declaration. +

    + + Gadget g(Widget i); + +

    + As a result, this program is well-formed and prints only + + 3 + + as output because no + + Gadget + + or + + Widget + + objects are constructed. +

    -

    This compliant solution demonstrates two equally compliant ways to write the declaration of g. The first declaration, g1, uses an extra set of parentheses around the argument to the constructor call, forcing the compiler to parse it as a local variable declaration of type Gadget instead of as a function declaration. The second declaration, g2, uses direct initialization to similar effect.

    - #include <iostream> +

    + This compliant solution demonstrates two equally compliant ways to write the declaration of + + g + + . The first declaration, + + g1 + + , uses an extra set of parentheses around the argument to the constructor call, forcing the compiler to parse it as a local variable declaration of type + + Gadget + + instead of as a function declaration. The second declaration, + + g2 + + , uses direct initialization to similar effect. +

    + + #include <iostream> struct Widget { explicit Widget(int i) { std::cout << "Widget constructed" << std::endl; } @@ -105,16 +256,22 @@ void f() { Gadget g2{Widget(i)}; // Use direct initialization std::cout << i << std::endl; } - -

    Running this program produces the expected output.

    - Widget constructed + +

    + Running this program produces the expected output. +

    + + Widget constructed Gadget constructed Widget constructed Gadget constructed -3 +3 +
    -

    Syntactically ambiguous declarations can lead to unexpected program execution. However, it is likely that rudimentary testing would uncover violations of this rule.

    +

    + Syntactically ambiguous declarations can lead to unexpected program execution. However, it is likely that rudimentary testing would uncover violations of this rule. +

    @@ -151,10 +308,14 @@ Gadget constructed Medium @@ -187,7 +348,9 @@ Gadget constructed 2021.2 @@ -202,7 +365,11 @@ Gadget constructed 2021.4 @@ -216,8 +383,11 @@ Gadget constructed @@ -272,7 +447,9 @@ Gadget constructed 4.4 @@ -287,7 +464,9 @@ Gadget constructed 3.9 @@ -302,7 +481,11 @@ Gadget constructed 4.10 @@ -311,7 +494,17 @@ Gadget constructed
    - P2 + + P2 + - L3 + + L3 +
    - C++2502, C++2510 + + C++2502, C++2510 + - CERT.DCL.AMBIGUOUS_DECL + + + CERT.DCL.AMBIGUOUS_DECL + + - 296 S - + + 296 S + + + Partially implemented @@ -233,8 +403,13 @@ Gadget constructed 2021.2 - CERT_CPP-DCL53-a - CERT_CPP-DCL53-bCERT_CPP-DCL53-c + + CERT_CPP-DCL53-a + + + CERT_CPP-DCL53-b + CERT_CPP-DCL53-c + Parameter names in function declarations should not be enclosed in parentheses @@ -258,7 +433,7 @@ Gadget constructed Checks for declarations that can be confused between: - Function and object declarationunction and object declaration, unnamed object or function parameter declarationnnamed object or function parameter declaration. + Function and object declaration, unnamed object or function parameter declaration. Rule fully covered.
    - 2502, 2510 + + 2502, 2510 + - -Wvexing-parse + + -Wvexing-parse + - S3468 + + + S3468 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction-standard.qhelp b/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction-standard.qhelp index bc316eb78e..d9d60d4bf4 100644 --- a/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction-standard.qhelp +++ b/cpp/cert/src/rules/DCL54-CPP/SingularOverloadOfMemoryFunction-standard.qhelp @@ -1,16 +1,59 @@
    -

    Allocation and deallocation functions can be overloaded at both global and class scopes.

    -

    If an allocation function is overloaded in a given scope, the corresponding deallocation function must also be overloaded in the same scope (and vice versa).

    -

    Failure to overload the corresponding dynamic storage function is likely to violate rules such as MEM51-CPP. Properly deallocate dynamically allocated resources. For instance, if an overloaded allocation function uses a private heap to perform its allocations, passing a pointer returned by it to the default deallocation function will likely cause undefined behavior. Even in situations in which the allocation function ultimately uses the default allocator to obtain a pointer to memory, failing to overload a corresponding deallocation function may leave the program in an unexpected state by not updating internal data for the custom allocator.

    -

    It is acceptable to define a deleted allocation or deallocation function without its corresponding free store function. For instance, it is a common practice to define a deleted non-placement allocation or deallocation function as a class member function when the class also defines a placement new function. This prevents accidental allocation via calls to new for that class type or deallocation via calls to delete on pointers to an object of that class type. It is acceptable to declare, but not define, a private allocation or deallocation function without its corresponding free store function for similar reasons. However, a definition must not be provided as that still allows access to the free store function within a class member function.

    +

    + Allocation and deallocation functions can be overloaded at both global and class scopes. +

    +

    + If an allocation function is overloaded in a given scope, the corresponding deallocation function must also be overloaded in the same scope (and vice versa). +

    +

    + Failure to overload the corresponding dynamic storage function is likely to violate rules such as + + MEM51-CPP. Properly deallocate dynamically allocated resources + + . For instance, if an overloaded allocation function uses a private heap to perform its allocations, passing a pointer returned by it to the default deallocation function will likely cause + + undefined behavior + + . Even in situations in which the allocation function ultimately uses the default allocator to obtain a pointer to memory, failing to overload a corresponding deallocation function may leave the program in an unexpected state by not updating internal data for the custom allocator. +

    +

    + It is acceptable to define a deleted allocation or deallocation function without its corresponding + + free store + + function. For instance, it is a common practice to define a deleted non-placement allocation or deallocation function as a class member function when the class also defines a placement + + new + + function. This prevents accidental allocation via calls to + + new + + for that class type or deallocation via calls to + + delete + + on pointers to an object of that class type. It is acceptable to declare, but not define, a private allocation or deallocation function without its corresponding free store function for similar reasons. However, a definition must not be provided as that still allows access to the free store function within a class member function. +

    -

    In this noncompliant code example, an allocation function is overloaded at global scope. However, the corresponding deallocation function is not declared. Were an object to be allocated with the overloaded allocation function, any attempt to delete the object would result in undefined behavior in violation of MEM51-CPP. Properly deallocate dynamically allocated resources.

    - #include <Windows.h> +

    + In this noncompliant code example, an allocation function is overloaded at global scope. However, the corresponding deallocation function is not declared. Were an object to be allocated with the overloaded allocation function, any attempt to delete the object would result in + + undefined behavior + + in violation of + + MEM51-CPP. Properly deallocate dynamically allocated resources + + . +

    + + #include <Windows.h> #include <new> - +ย  void *operator new(std::size_t size) noexcept(false) { static HANDLE h = ::HeapCreate(0, 0, 0); // Private, expandable heap. if (h) { @@ -18,66 +61,94 @@ void *operator new(std::size_t size) noexcept(false) { } throw std::bad_alloc(); } - -// No corresponding global delete operator defined. +ย  +// No corresponding global delete operator defined. +
    -

    In this compliant solution, the corresponding deallocation function is also defined at global scope.

    - #include <Windows.h> +

    + In this compliant solution, the corresponding deallocation function is also defined at global scope. +

    + + #include <Windows.h> #include <new> class HeapAllocator { static HANDLE h; static bool init; - +ย  public: static void *alloc(std::size_t size) noexcept(false) { if (!init) { h = ::HeapCreate(0, 0, 0); // Private, expandable heap. init = true; } - +ย  if (h) { return ::HeapAlloc(h, 0, size); } throw std::bad_alloc(); } - +ย  static void dealloc(void *ptr) noexcept { if (h) { (void)::HeapFree(h, 0, ptr); } } }; - +ย  HANDLE HeapAllocator::h = nullptr; bool HeapAllocator::init = false; void *operator new(std::size_t size) noexcept(false) { return HeapAllocator::alloc(size); } - +ย  void operator delete(void *ptr) noexcept { return HeapAllocator::dealloc(ptr); -} +} +
    -

    In this noncompliant code example, operator new() is overloaded at class scope, but operator delete() is not similarly overloaded at class scope. Despite that the overloaded allocation function calls through to the default global allocation function, were an object of type S to be allocated, any attempt to delete the object would result in leaving the program in an indeterminate state due to failing to update allocation bookkeeping accordingly.

    - #include <new> - +

    + In this noncompliant code example, + + operator new() + + is overloaded at class scope, but + + operator delete() + + is not similarly overloaded at class scope. Despite that the overloaded allocation function calls through to the default global allocation function, were an object of type + + S + + to be allocated, any attempt to delete the object would result in leaving the program in an indeterminate state due to failing to update allocation bookkeeping accordingly. +

    + + #include <new> +ย  extern "C++" void update_bookkeeping(void *allocated_ptr, std::size_t size, bool alloc); - +ย  struct S { void *operator new(std::size_t size) noexcept(false) { void *ptr = ::operator new(size); update_bookkeeping(ptr, size, true); return ptr; } -}; +}; +
    -

    In this compliant solution, the corresponding operator delete() is overloaded at the same class scope.

    - #include <new> +

    + In this compliant solution, the corresponding + + operator delete() + + is overloaded at the same class scope. +

    + + #include <new> extern "C++" void update_bookkeeping(void *allocated_ptr, std::size_t size, bool alloc); @@ -87,18 +158,58 @@ struct S { update_bookkeeping(ptr, size, true); return ptr; } - +ย  void operator delete(void *ptr, std::size_t size) noexcept { ::operator delete(ptr); update_bookkeeping(ptr, size, false); } -}; +}; +
    -

    DCL54-CPP-EX1: A placement deallocation function may be elided for a corresponding placement allocation function, but only if the object placement allocation and object construction are guaranteed to be noexcept(true). Because placement deallocation functions are automatically invoked when the object initialization terminates by throwing an exception, it is safe to elide the placement deallocation function when exceptions cannot be thrown. For instance, some vendors implement compiler flags disabling exception support (such as -fno-cxx-exceptions in Clang and /EHs-c- in Microsoft Visual Studio), which has implementation-defined behavior when an exception is thrown but generally results in program termination similar to calling abort().

    +

    + + DCL54-CPP-EX1: + + A placement deallocation function may be elided for a corresponding placement allocation function, but only if the object placement allocation and object construction are guaranteed to be + + noexcept(true) + + . Because placement deallocation functions are automatically invoked when the object initialization terminates by throwing an exception, it is safe to elide the placement deallocation function when exceptions cannot be thrown.ย For instance, some vendors implement compiler flags disabling exception support (such as -fno-cxx-exceptions in + + Clang + + and /EHs-c- in + + Microsoft Visual Studio + + ), which has + + implementation-defined behavior + + when an exception is thrown but generally results in program termination similar to calling + + abort() + + . +

    -

    Mismatched usage of new and delete could lead to a denial-of-service attack.

    +

    + Mismatched usage of + + new + + and + + delete + + could lead to a + + denial-of-service attack + + . +

    @@ -135,10 +246,14 @@ struct S { Low @@ -171,7 +286,9 @@ struct S { 20.10 @@ -202,11 +321,15 @@ struct S { 3.9 @@ -220,7 +343,9 @@ struct S { 2021.2 @@ -235,7 +360,11 @@ struct S { 2021.4 @@ -250,7 +379,9 @@ struct S { 2021.2 @@ -299,7 +432,9 @@ struct S { 20.10 @@ -324,7 +463,17 @@ struct S {
    - P6 + + P6 + - L2 + + L2 +
    - new-delete-pairwise + + new-delete-pairwise + Partially checked @@ -187,7 +304,9 @@ struct S { 7.2.0 - CertC++-DCL54 + + CertC++-DCL54 + - misc-new-delete-overloads + + misc-new-delete-overloads + Checked with - clang-tidy + + clang-tidy + .
    - C++2160 + + C++2160 + - CERT.DCL.SAME_SCOPE_ALLOC_DEALLOC + + + CERT.DCL.SAME_SCOPE_ALLOC_DEALLOC + + - CERT_CPP-DCL54-a + + CERT_CPP-DCL54-a + Always provide new and delete together @@ -284,7 +415,9 @@ struct S { 4.4 - 2160 + + 2160 + - new-delete-pairwise + + new-delete-pairwise + Partially checked @@ -315,7 +450,11 @@ struct S { 4.10 - S1265 + + + S1265 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries-standard.qhelp b/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries-standard.qhelp index 30bc946966..0c27e8be72 100644 --- a/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries-standard.qhelp +++ b/cpp/cert/src/rules/DCL55-CPP/InformationLeakageAcrossTrustBoundaries-standard.qhelp @@ -1,62 +1,131 @@
    -

    The C++ Standard, [class.mem], paragraph 13 [ISO/IEC 14882-2014], describes the layout of non-static data members of a non-union class, specifying the following:

    +

    + The C++ Standard, [class.mem], paragraph 13 [ + + ISO/IEC 14882-2014 + + ], describes the layout of non-static data members of a non-union class, specifying the following: +

    -

    Nonstatic data members of a (non-union) class with the same access control are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified. Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions and virtual base classes.

    +

    + Nonstatic data members of a (non-union) class with the same access controlย are allocated soย that later members have higher addresses within a class object. The order of allocation of non-static dataย members with different access control is unspecified. Implementation alignment requirementsย might cause two adjacent members not to be allocated immediately after each other; so might requirementsย for space for managing virtual functionsย and virtual base classes. +

    -

    Further, [class.bit], paragraph 1, in part, states the following:

    +

    + Further,ย [class.bit], paragraph 1,ย in part, states the following: +

    -

    Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit.

    +

    + Allocation of bit-fields within a class object isย implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into someย addressable allocation unit. +

    -

    Thus, padding bits may be present at any location within a class object instance (including at the beginning of the object, in the case of an unnamed bit-field as the first member declared in a class). Unless initialized by zero-initialization, padding bits contain indeterminate values that may contain sensitive information.

    -

    When passing a pointer to a class object instance across a trust boundary to a different trusted domain, the programmer must ensure that the padding bits of such an object do not contain sensitive information.

    +

    + Thus, padding bits may be present at any location within a class object instance (including at the beginning of the object, in the case of an unnamed bit-field as the first member declared in a class). Unless initialized by zero-initialization, padding bits contain + + indeterminate values + + that may contain sensitive information. +

    +

    + When passing a pointer to a class object instance across a + + trust boundary + + to a different trusted domain, the programmer must ensure that the padding bits of such an object do not contain sensitive information. +

    -

    This noncompliant code example runs in kernel space and copies data from arg to user space. However, padding bits may be used within the object, for example, to ensure the proper alignment of class data members. These padding bits may contain sensitive information that may then be leaked when the data is copied to user space, regardless of how the data is copied.

    - #include <cstddef> - +

    + This noncompliant code example runs in kernel space and copies data from + + arg + + to user space.ย However, padding bits may be used within the object, for example, to ensure the proper alignment of class data members. These padding bits may contain sensitive information that may then be leaked when the data is copied to user space, regardless of how the data is copied. +

    + + #include <cstddef> +ย  struct test { int a; char b; int c; }; - +ย  // Safely copy bytes to user space extern int copy_to_user(void *dest, void *src, std::size_t size); - +ย  void do_stuff(void *usr_buf) { test arg{1, 2, 3}; copy_to_user(usr_buf, &arg, sizeof(arg)); -} +} +
    -

    In this noncompliant code example, arg is value-initialized through direct initialization. Because test does not have a user-provided default constructor, the value-initialization is preceded by a zero-initialization that guarantees the padding bits are initialized to 0 before any further initialization occurs. It is akin to using std::memset() to initialize all of the bits in the object to 0.

    - #include <cstddef> - +

    + In this noncompliant code example, + + arg + + is value-initialized through direct initialization. Because + + test + + does not have a user-provided default constructor, the value-initialization is preceded by a zero-initialization that guarantees the padding bits are initialized to + + 0 + + before any further initialization occurs. It is akin to using + + std::memset() + + to initialize all of the bits in the object to + + 0 + + . +

    + + #include <cstddef> +ย  struct test { int a; char b; int c; }; - +ย  // Safely copy bytes to user space extern int copy_to_user(void *dest, void *src, std::size_t size); - +ย  void do_stuff(void *usr_buf) { test arg{}; - +ย  arg.a = 1; arg.b = 2; arg.c = 3; - +ย  copy_to_user(usr_buf, &arg, sizeof(arg)); -} -

    However, compilers are free to implement arg.b = 2 by setting the low byte of a 32-bit register to 2, leaving the high bytes unchanged, and storing all 32 bits of the register into memory. This could leak the high-order bytes resident in the register to a user.

    +} +
    +

    + However, compilers are free to implement + + arg.b = 2 + + by setting the low byte of a 32-bit register to + + 2 + + , leaving the high bytes unchanged, and storing all 32 bits of the register into memory. This could leak the high-order bytes resident in the register to a user. +

    -

    This compliant solution serializes the structure data before copying it to an untrusted context.

    - #include <cstddef> +

    + This compliant solution serializes the structure data before copying it to an untrusted context. +

    + + #include <cstddef> #include <cstring> struct test { @@ -82,19 +151,29 @@ void do_stuff(void *usr_buf) { offset += sizeof(arg.c); copy_to_user(usr_buf, buf, offset /* size of info copied */); -} -

    This code ensures that no uninitialized padding bits are copied to unprivileged users. The structure copied to user space is now a packed structure and the copy_to_user() function would need to unpack it to recreate the original, padded structure.

    +} +
    +

    + This code ensures that no uninitialized padding bits are copied to unprivileged users. The structure copied to user space is now a packed structure and the + + copy_to_user() + + function would need to unpack it to recreate the original, padded structure. +

    -

    Padding bits can be explicitly declared as fields within the structure. This solution is not portable, however, because it depends on the implementation and target memory architecture. The following solution is specific to the x86-32 architecture.

    - #include <cstddef> +

    + Padding bits can be explicitly declared as fields within the structure. This solution is not portable, however, because it depends on theย implementationย and target memory architecture. The following solution is specific to the x86-32 architecture. +

    + + #include <cstddef> struct test { int a; char b; char padding_1, padding_2, padding_3; int c; - +ย  test(int a, char b, int c) : a(a), b(b), padding_1(0), padding_2(0), padding_3(0), c(c) {} @@ -114,22 +193,60 @@ extern int copy_to_user(void *dest, void *src, std::size_t size); void do_stuff(void *usr_buf) { test arg{1, 2, 3}; copy_to_user(usr_buf, &arg, sizeof(arg)); -} -

    The static_assert() declaration accepts a constant expression and an error message. The expression is evaluated at compile time and, if false, the compilation is terminated and the error message is used as the diagnostic. The explicit insertion of the padding bytes into the struct should ensure that no additional padding bytes are added by the compiler, and consequently both static assertions should be true. However, it is necessary to validate these assumptions to ensure that the solution is correct for a particular implementation.

    +} +
    +

    + The + + static_assert() + + declaration accepts a constant expression and an + + error message + + . The expression is evaluated at compile time and, if false, the compilation is terminated and the error message is used as the diagnostic. The explicit insertion of the padding bytes into the + + struct + + should ensure that noย additional padding bytes are added by the compiler, and consequently both static assertions should be true. However, it is necessary to validate these assumptions to ensure that the solution is correct for a particular implementation. +

    -

    In this noncompliant code example, padding bits may abound, including

    +

    + In this noncompliant code example, padding bits may abound, including +

      -
    • alignment padding bits after a virtual method table or virtual base class data to align a subsequent data member,
    • -
    • alignment padding bits to position a subsequent data member on a properly aligned boundary,
    • -
    • alignment padding bits to position data members of varying access control levels.
    • -
    • bit-field padding bits when the sequential set of bit-fields does not fill an entire allocation unit,
    • -
    • bit-field padding bits when two adjacent bit-fields are declared with different underlying types,
    • -
    • padding bits when a bit-field is declared with a length greater than the number of bits in the underlying allocation unit, or
    • -
    • padding bits to ensure a class instance will be appropriately aligned for use within an array.
    • +
    • + alignment padding bits after a virtual method table or virtual base class data to align a subsequent data member, +
    • +
    • + alignment padding bits to position a subsequent data member on a properly aligned boundary, +
    • +
    • + alignment padding bits to position data members of varying access control levels. +
    • +
    • + bit-field padding bits when the sequential set of bit-fields does not fill an entire allocation unit, +
    • +
    • + bit-field padding bits when two adjacent bit-fields are declared with different underlying types, +
    • +
    • + padding bits when a bit-field is declared with a length greater than the number of bits in the underlying allocation unit, or +
    • +
    • + padding bits to ensure a class instance will be appropriately aligned for use within an array. +
    -

    This code example runs in kernel space and copies data from arg to user space. However, the padding bits within the object instance may contain sensitive information that will then be leaked when the data is copied to user space.

    - #include <cstddef> +

    + This code example runs in kernel space and copies data from + + arg + + to user space.ย However, the padding bits within the object instance may contain sensitive information that will then be leaked when the data is copied to user space. +

    + + #include <cstddef> class base { public: @@ -161,8 +278,19 @@ extern int copy_to_user(void *dest, void *src, std::size_t size); void do_stuff(void *usr_buf) { test arg{0.0, 1, 2, 3, 4, 5, 6, 7.0}; copy_to_user(usr_buf, &arg, sizeof(arg)); -} -

    Padding bits are implementation-defined, so the layout of the class object may differ between compilers or architectures. When compiled with GCC 5.3.0 for x86-32, the test object requires 96 bytes of storage to accommodate 29 bytes of data (33 bytes including the vtable) and has the following layout.

    +} +
    +

    + Padding bits are implementation-defined, so the layout of the class object may differ between compilers or architectures.ย When compiled with + + GCC + + 5.3.0 for x86-32, the + + test + + object requires 96 bytes of storage to accommodate 29 bytes of data (33 bytes including the vtable) and has the following layout. +

    @@ -206,7 +334,9 @@ void do_stuff(void *usr_buf) { 4 (32) @@ -228,7 +358,9 @@ void do_stuff(void *usr_buf) { 0 (4) @@ -239,7 +371,9 @@ void do_stuff(void *usr_buf) { 8 (64) @@ -250,7 +384,9 @@ void do_stuff(void *usr_buf) { 0 (3) @@ -261,7 +397,9 @@ void do_stuff(void *usr_buf) { 1 (8) @@ -295,7 +433,9 @@ void do_stuff(void *usr_buf) { 1 (8) @@ -306,7 +446,9 @@ void do_stuff(void *usr_buf) { 4 (32) @@ -339,7 +481,9 @@ void do_stuff(void *usr_buf) { 8 (64) @@ -368,8 +512,11 @@ void do_stuff(void *usr_buf) {
    - unsigned k + + unsigned k +
    - unsigned l : 4 + + unsigned l : 4 +
    - double h + + double h + - unsigned short m : 3 + + unsigned short m : 3 +
    - char i + + char i + - char n + + char n +
    - unsigned j : 80 + + unsigned j : 80 + - double o + + double o +
    -

    Due to the complexity of the data structure, this compliant solution serializes the object data before copying it to an untrusted context instead of attempting to account for all of the padding bytes manually.

    - #include <cstddef> +

    + Due to the complexity of the data structure, this compliant solution serializes the object data beforeย copying it to an untrusted context instead of attempting to account for all of the padding bytes manually. +

    + + #include <cstddef> #include <cstring> class base { @@ -439,11 +586,20 @@ void do_stuff(void *usr_buf) { } else { // Handle error } -} -

    This code ensures that no uninitialized padding bits are copied to unprivileged users. The structure copied to user space is now a packed structure and the copy_to_user() function would need to unpack it to re-create the original, padded structure.

    +} +
    +

    + This code ensures that no uninitialized padding bits are copied to unprivileged users. The structure copied to user space is now a packed structure and the + + copy_to_user() + + function would need to unpack it to re-create the original, padded structure. +

    -

    Padding bits might inadvertently contain sensitive data such as pointers to kernel data structures or passwords. A pointer to such a structure could be passed to other functions, causing information leakage.

    +

    + Padding bits mightย inadvertentlyย contain sensitive data such as pointers to kernel data structures or passwords.ย A pointer to such a structure could be passed to other functions, causing information leakage. +

    @@ -480,10 +636,14 @@ void do_stuff(void *usr_buf) { High @@ -516,7 +676,9 @@ void do_stuff(void *usr_buf) { 7.2.0 @@ -531,7 +693,9 @@ void do_stuff(void *usr_buf) { 2021.2 @@ -546,7 +710,9 @@ void do_stuff(void *usr_buf) { 2021.2
    - P1 + + P1 + - L3 + + L3 +
    - CertC++-DCL55 + + CertC++-DCL55 + - C++4941, C++4942, C++4943 + + C++4941, C++4942, C++4943 + - CERT_CPP-DCL55-a + + CERT_CPP-DCL55-a + A pointer to a structure should not be passed to a function that can copy data to the user space @@ -556,11 +722,61 @@ void do_stuff(void *usr_buf) {
    -

    Numerous vulnerabilities in the Linux Kernel have resulted from violations of this rule.

    -

    CVE-2010-4083 describes a vulnerability in which the semctl() system call allows unprivileged users to read uninitialized kernel stack memory because various fields of a semid_ds struct declared on the stack are not altered or zeroed before being copied back to the user.

    -

    CVE-2010-3881 describes a vulnerability in which structure padding and reserved fields in certain data structures in QEMU-KVM were not initialized properly before being copied to user space. A privileged host user with access to /dev/kvm could use this flaw to leak kernel stack memory to user space.

    -

    CVE-2010-3477 describes a kernel information leak in act_police where incorrectly initialized structures in the traffic-control dump code may allow the disclosure of kernel memory to user space applications.

    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Numerous vulnerabilities in the Linux Kernel have resulted from violations of this rule. +

    +

    + + CVE-2010-4083 + + describes aย vulnerability + in which the + + semctl() + + system call allows unprivileged users to read uninitialized kernel stack memory because various fields of a + + semid_ds struct + + declared on the stack are not altered or zeroed before being copied back to the user. +

    +

    + + CVE-2010-3881 + + describes a vulnerability in which structure padding and reserved fields in certain data structures in + + QEMU-KVM + + were not initialized properly before being copied to user space. A privileged host user with access to + + /dev/kvm + + could use this + flaw + to leak kernel stack memory to user space. +

    +

    + + CVE-2010-3477 + + describes a kernel information leak in + + act_police + + where incorrectly initialized structures in the traffic-control dump code may allow the disclosure of kernel memory to user space applications. +

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit-standard.qhelp b/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit-standard.qhelp index 8fc2bf64eb..d5737e0b1b 100644 --- a/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit-standard.qhelp +++ b/cpp/cert/src/rules/DCL56-CPP/CyclesDuringStaticObjectInit-standard.qhelp @@ -1,21 +1,58 @@
    -

    The C++ Standard, [stmt.dcl], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard, [stmt.dcl], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , states the following: +

    -

    The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of a block-scope entity with static storage duration, if applicable, is performed before its block is first entered. An implementation is permitted to perform early initialization of other block-scope variables with static or thread storage duration under the same conditions that an implementation is permitted to statically initialize a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

    +

    + The zero-initialization (8.5) of all block-scope variables with static storage duration (3.7.1) or thread storageย duration (3.7.2) is performed before any other initialization takes place. Constant initialization (3.6.2) of aย block-scope entity with static storage duration, if applicable, is performed before its block is first entered.ย An implementation is permitted to perform early initialization of other block-scope variables with static orย thread storage duration under the same conditions that an implementation is permitted to statically initializeย a variable with static or thread storage duration in namespace scope (3.6.2). Otherwise such a variable isย initialized the first time control passes through its declaration; such a variable is considered initialized uponย the completion of its initialization. If the initialization exits by throwing an exception, the initializationย is not complete, so it will be tried again the next time control enters the declaration. If control entersย the declaration concurrently while the variable is being initialized, the concurrent execution shall wait forย completion of the initialization.ย If control re-enters the declaration recursively while the variable is beingย initialized, the behavior is undefined. +

    -

    Do not reenter a function during the initialization of a static variable declaration. If a function is reentered during the constant initialization of a static object inside that function, the behavior of the program is undefined. Infinite recursion is not required to trigger undefined behavior, the function need only recur once as part of the initialization. Due to thread-safe initialization of variables, a single, recursive call will often result in a deadlock due to locking a non-recursive synchronization primitive.

    -

    Additionally, the C++ Standard, [basic.start.init], paragraph 2, in part, states the following:

    +

    + Do not reenter a function during the initialization of a static variable declaration.ย If a function is reentered during the constant initialization of a static object inside that function, the behavior of the program is + + undefined + + . Infinite recursion is not required to trigger undefined behavior, the function need only recur once as part of the initialization. Due to thread-safe initialization of variables, a single, recursive call will often result in a + + deadlock + + due to locking a non-recursive synchronization primitive. +

    +

    + Additionally, the C++ Standard,ย [basic.start.init], paragraph 2,ย in part, states the following: +

    -

    Dynamic initialization of a non-local variable with static storage duration is either ordered or unordered. Definitions of explicitly specialized class template static data members have ordered initialization. Other class template static data members (i.e., implicitly or explicitly instantiated specializations) have unordered initialization. Other non-local variables with static storage duration have ordered initialization. Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit. If a program starts a thread, the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit. If a program starts a thread, the subsequent unordered initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization.

    +

    + Dynamic initialization of a non-local variable with static storage duration is either ordered orย unordered. Definitions of explicitly specialized class template static data members have ordered initialization. Other class template static data members (i.e., implicitly or explicitly instantiated specializations) haveย unordered initialization. Other non-local variables with static storage duration have ordered initialization.ย Variables with ordered initialization defined within a single translation unit shall be initialized in the orderย of their definitions in the translation unit. If a program starts a thread, the subsequent initializationย of a variable is unsequenced with respect to the initialization of a variable defined in a different translationย unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initializationย of a variable defined in a different translation unit. If a program starts a thread, the subsequent unorderedย initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise,ย the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamicย initialization. +

    -

    Do not create an initialization interdependency between static objects with dynamic initialization unless they are ordered with respect to one another. Unordered initialization, especially prevalent across translation unit boundaries, results in unspecified behavior.

    +

    + Do not create an initialization interdependency between static objects with dynamic initialization unless they are ordered with respect to one another. Unordered initialization, especially prevalent across translation unit boundaries, results in + + unspecified behavior + + . +

    -

    This noncompliant example attempts to implement an efficient factorial function using caching. Because the initialization of the static local array cache involves recursion, the behavior of the function is undefined, even though the recursion is not infinite.

    - #include <stdexcept> - +

    + This noncompliant example attempts to implement an efficient factorial function using caching. Because the initialization of the static local array + + cache + + involves recursion, the behavior of the function is undefined, even though the recursion is not infinite. +

    + + #include <stdexcept> +ย  int fact(int i) noexcept(false) { if (i < 0) { // Negative factorials are undefined. @@ -34,14 +71,39 @@ int fact(int i) noexcept(false) { return i > 0 ? i * fact(i - 1) : 1; } - -

    Implementation Details

    -

    In Microsoft Visual Studio 2015 and GCC 6.1.0, the recursive initialization of cache deadlocks while initializing the static variable in a thread-safe manner.

    +
    +

    + + Implementation Details + +

    +

    + In + + Microsoft Visual Studio + + 2015 and + + GCC + + 6.1.0, the recursive initialization of + + cache + + deadlocks while initializing the static variableย in a thread-safe manner. +

    -

    This compliant solution avoids initializing the static local array cache and instead relies on zero-initialization to determine whether each member of the array has been assigned a value yet and, if not, recursively computes its value. It then returns the cached value when possible or computes the value as needed.

    - #include <stdexcept> - +

    + This compliant solution avoids initializing the static local array + + cache + + and instead relies on zero-initialization to determine whether each member of the array has been assigned a value yet and, if not, recursively computes its value. It then returns the cached value when possible or computes the value as needed. +

    + + #include <stdexcept> +ย  int fact(int i) noexcept(false) { if (i < 0) { // Negative factorials are undefined. @@ -56,50 +118,163 @@ int fact(int i) noexcept(false) { } return cache[i]; } - +ย  return i > 0 ? i * fact(i - 1) : 1; } - +
    -

    In this noncompliant code example, the value of numWheels in file1.cpp relies on c being initialized. However, because c is defined in a different translation unit (file2.cpp) than numWheels, there is no guarantee that c will be initialized by calling get_default_car() before numWheels is initialized by calling c.get_num_wheels(). This is often referred to as the "static initialization order fiasco," and the resulting behavior is unspecified.

    - // file.h +

    + In this noncompliant code example, the value of + + numWheels + + in + + file1.cpp + + relies on + + c + + being initialized. However, because + + c + + is defined in a different translation unit ( + + file2.cpp + + ) than + + numWheels + + , there is no guarantee that + + c + + will be initialized by calling + + get_default_car() + + before + + numWheels + + is initialized by calling + + c.get_num_wheels() + + . This is often referred to as the " + + static initialization order fiasco + + ," and the resulting behavior is unspecified. +

    + + // file.h #ifndef FILE_H #define FILE_H - +ย  class Car { int numWheels; - +ย  public: Car() : numWheels(4) {} explicit Car(int numWheels) : numWheels(numWheels) {} - +ย  int get_num_wheels() const { return numWheels; } }; #endif // FILE_H - +ย  // file1.cpp #include "file.h" #include <iostream> - +ย  extern Car c; int numWheels = c.get_num_wheels(); - +ย  int main() { std::cout << numWheels << std::endl; } - +ย  // file2.cpp #include "file.h" - +ย  Car get_default_car() { return Car(6); } -Car c = get_default_car(); -

    Implementation Details

    -

    The value printed to the standard output stream will often rely on the order in which the translation units are linked. For instance, with Clang 3.8.0 on x86 Linux, the command clang++ file1.cpp file2.cpp && ./a.out will write 0 while clang++ file2.cpp file1.cpp && ./a.out will write 6.

    +Car c = get_default_car(); +
    +

    + + Implementation Details + +

    +

    + The value printed to the standard output stream will often rely on the order in which the translation units are linked. For instance, with + + Clang + + 3.8.0 on x86 Linux, the command + + clang++ file1.cpp file2.cpp && ./a.out + + will write + + 0 + + while + + clang++ file2.cpp file1.cpp && ./a.out + + will write + + 6 + + . +

    -

    This compliant solution uses the "construct on first use" idiom to resolve the static initialization order issue. The code for file.h and file2.cpp are unchanged; only the static numWheels in file1.cpp is moved into the body of a function. Consequently, the initialization of numWheels is guaranteed to happen when control flows over the point of declaration, ensuring control over the order. The global object c is initialized before execution of main() begins, so by the time get_num_wheels() is called, c is guaranteed to have already been dynamically initialized.

    - // file.h +

    + This compliant solution uses the "construct on first use" idiom to resolve the static initialization order issue. The code for + + file.h + + and + + file2.cpp + + are unchanged; only the static + + numWheels + + in + + file1.cpp + + is moved into the body of a function. Consequently, theย initialization of + + numWheels + + is guaranteed to happen when control flows over the point of declaration, ensuring control over the order. The global object + + c + + is initialized beforeย execution of + + main() + + begins, so by the time + + get_num_wheels() + + is called, + + c + + is guaranteed to have already been dynamically initialized. +

    + + // file.h #ifndef FILE_H #define FILE_H @@ -132,10 +307,17 @@ int main() { #include "file.h" Car get_default_car() { return Car(6); } -Car c = get_default_car(); +Car c = get_default_car(); +
    -

    Recursively reentering a function during the initialization of one of its static objects can result in an attacker being able to cause a crash or denial of service. Indeterminately ordered dynamic initialization can lead to undefined behavior due to accessing an uninitialized object.

    +

    + Recursively reentering a function during the initialization of one of its static objects can result in an attacker being able to cause a crash or + + denial of service + + . Indeterminately ordered dynamic initialization can lead to undefined behavior due to accessing an uninitialized object. +

    @@ -172,10 +354,14 @@ Car c = get_default_car(); Medium @@ -198,24 +384,6 @@ Car c = get_default_car(); Description - - - - - - @@ -240,7 +410,9 @@ Car c = get_default_car();
    - P2 + + P2 + - L3 + + L3 +
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.INIT.CYCLE - LANG.STRUCT.INIT.UNORDERED - - Initialization Cycle - Unordered Initialization -
    @@ -226,7 +394,9 @@ Car c = get_default_car(); 2021.2 - C++1552, C++1554, C++1704 + + C++1552, C++1554, C++1704 + - 6 D + + 6 D + Enhanced Enforcement @@ -256,7 +428,9 @@ Car c = get_default_car(); 2021.2 - CERT_CPP-DCL56-a + + CERT_CPP-DCL56-a + Avoid initialization order problems across translation units by replacing non-local static objects with local static objects @@ -266,7 +440,17 @@ Car c = get_default_car();
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions-standard.qhelp b/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions-standard.qhelp index 9af0a14d9e..d5f3ddb61a 100644 --- a/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions-standard.qhelp +++ b/cpp/cert/src/rules/DCL57-CPP/DoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions-standard.qhelp @@ -1,31 +1,146 @@
    -

    Under certain circumstances, terminating a destructor, operator delete, or operator delete[] by throwing an exception can trigger undefined behavior.

    -

    For instance, the C++ Standard, [basic.stc.dynamic.deallocation], paragraph 3 [ISO/IEC 14882-2014], in part, states the following:

    +

    + Under certain circumstances, terminating a destructor, + + operator delete + + , or + + operator delete[] + + by throwing an exception can trigger + + undefined behavior + + . +

    +

    + For instance,ย the C++ Standard,ย [basic.stc.dynamic.deallocation], paragraph 3 [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    If a deallocation function terminates by throwing an exception, the behavior is undefined.

    +

    + If a deallocation function terminates by throwing an exception, the behavior is undefined. +

    -

    In these situations, the function must logically be declared noexcept because throwing an exception from the function can never have well-defined behavior. The C++ Standard, [except.spec], paragraph 15, states the following:

    +

    + In these situations, the function must logically be declared + + noexcept + + because throwing an exception from the function can never have well-defined behavior. The C++ Standard,ย [except.spec], paragraph 15, states the following: +

    -

    A deallocation function with no explicit exception-specification is treated as if it were specified with noexcept(true).

    +

    + A deallocation function with no explicit exception-specification is treated as if it were specified withย noexcept(true). +

    -

    As such, deallocation functions (object, array, and placement forms at either global or class scope) must not terminate by throwing an exception. Do not declare such functions to be noexcept(false). However, it is acceptable to rely on the implicit noexcept(true) specification or declare noexcept explicitly on the function signature.

    -

    Object destructors are likely to be called during stack unwinding as a result of an exception being thrown. If the destructor itself throws an exception, having been called as the result of an exception being thrown, then the function std::terminate() is called with the default effect of calling std::abort() [ISO/IEC 14882-2014]. When std::abort() is called, no further objects are destroyed, resulting in an indeterminate program state and undefined behavior. Do not terminate a destructor by throwing an exception.

    -

    The C++ Standard, [class.dtor], paragraph 3, states [ISO/IEC 14882-2014] the following:

    +

    + As such, deallocation functions (object, array, and placement forms at either global or class scope) must not terminate by throwing an exception. Do not declare such functions to be + + noexcept(false) + + . However,ย it is acceptable to rely on the implicit + + noexcept(true) + + specification or declare + + noexcept + + explicitly on the function signature. +

    +

    + Object destructors are likely to be called during stack unwinding as a result of an exception being thrown. If the destructor itself throws an exception, having been called as the result of an exception being thrown, then the function + + std::terminate() + + is called with the default effect of calling + + std::abort() + + [ + + ISO/IEC 14882-2014 + + ] + . + When + + std::abort() + + is called, no further objects are destroyed, resulting in an indeterminate program state and undefined behavior.ย Do not terminate a destructor by throwing an exception. +

    +

    + The C++ Standard,ย [class.dtor], paragraph 3, states [ + + ISO/IEC 14882-2014 + + ] the following: +

    -

    A declaration of a destructor that does not have an exception-specification is implicitly considered to have the same exception-specification as an implicit declaration.

    +

    + A declaration of a destructor that does not have an exception-specification is implicitly considered to haveย the same exception-specification as an implicit declaration. +

    -

    An implicit declaration of a destructor is considered to be noexcept(true) according to [except.spec], paragraph 14. As such, destructors must not be declared noexcept(false) but may instead rely on the implicit noexcept(true) or declare noexcept explicitly.

    -

    Any noexcept function that terminates by throwing an exception violates ERR55-CPP. Honor exception specifications.

    +

    + An implicit declaration of a destructor is considered to be + + noexcept(true) + + according toย [except.spec], paragraph 14. As such, destructors must not be declared + + noexcept(false) + + but may instead rely on the implicit + + noexcept(true) + + or declare + + noexcept + + explicitly. +

    +

    + Any + + noexcept + + functionย that terminates by throwing an exception violates + + ERR55-CPP. Honor exception specifications + + . +

    -

    In this noncompliant code example, the class destructor does not meet the implicit noexcept guarantee because it may throw an exception even if it was called as the result of an exception being thrown. Consequently, it is declared as noexcept(false) but still can trigger undefined behavior.

    - #include <stdexcept> - +

    + In this noncompliant code example, the class destructor does not meet the implicit + + noexcept + + guarantee because it may throw an exception even if it was called as the result of an exception being thrown. Consequently, it is declared as + + noexcept(false) + + but still can trigger + + undefined behavior + + . +

    + + #include <stdexcept> +ย  class S { bool has_error() const; - +ย  public: ~S() noexcept(false) { // Normal processing @@ -33,11 +148,19 @@ public: throw std::logic_error("Something bad"); } } -}; +}; +
    -

    Use of std::uncaught_exception() in the destructor solves the termination problem by avoiding the propagation of the exception if an existing exception is being processed, as demonstrated in this noncompliant code example. However, by circumventing normal destructor processing, this approach may keep the destructor from releasing important resources.

    - #include <exception> +

    + Use of + + std::uncaught_exception() + + in the destructor solves the termination problem by avoiding the propagation of the exception if an existing exception is being processed, as demonstrated in this noncompliant code example.ย However, by circumventing normal destructor processing, this approach may keep the destructor from releasing important resources. +

    + + #include <exception> #include <stdexcept> class S { @@ -50,18 +173,41 @@ public: throw std::logic_error("Something bad"); } } -}; +}; +
    -

    This noncompliant code example, as well as the following compliant solution, presumes the existence of a Bad class with a destructor that can throw. Although the class violates this rule, it is presumed that the class cannot be modified to comply with this rule.

    - // Assume that this class is provided by a 3rd party and it is not something +

    + Thisย noncompliant code example, as well as the following compliant solution, presumesย the existence of a + + Bad + + class with a destructor that can throw. Although theย class violates this rule, it is presumed that the class cannot be modified to comply with this rule. +

    + + // Assume that this class is provided by a 3rd party and it is not something // that can be modified by the user. class Bad { ~Bad() noexcept(false); }; - -

    To safely use the Bad class, the SomeClass destructor attempts to handle exceptions thrown from the Bad destructor by absorbing them.

    - class SomeClass { + +

    + To safely use the + + Bad + + class,ย the + + SomeClass + + destructor attempts to handle exceptions thrown from the + + Bad + + destructorย by absorbing them. +

    + + class SomeClass { Bad bad_member; public: ~SomeClass() @@ -71,16 +217,61 @@ public: // Handle the exception thrown from the Bad destructor. } }; - -

    However, the C++ Standard, [except.handle], paragraph 15 [ISO/IEC 14882-2014], in part, states the following:

    +
    +

    + However, the C++ Standard, [except.handle], paragraph 15 [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    The currently handled exception is rethrown if control reaches the end of a handler of the function-try-block of a constructor or destructor.

    +

    + The currently handled exception is rethrown if control reaches the end of a handler of the function-try-blockย of a constructor or destructor. +

    -

    Consequently, the caught exception will inevitably escape from the SomeClass destructor because it is implicitly rethrown when control reaches the end of the function-try-block handler.

    +

    + Consequently, the caught exception will inevitably escape from the + + SomeClass + + destructor because it is implicitly rethrown when control reaches the end of the + + function-try-block + + handler. +

    -

    A destructor should perform the same way whether or not there is an active exception. Typically, this means that it should invoke only operations that do not throw exceptions, or it should handle all exceptions and not rethrow them (even implicitly). This compliant solution differs from the previous noncompliant code example by having an explicit return statement in the SomeClass destructor. This statement prevents control from reaching the end of the exception handler. Consequently, this handler will catch the exception thrown by Bad::~Bad() when bad_member is destroyed. It will also catch any exceptions thrown within the compound statement of the function-try-block, but the SomeClass destructor will not terminate by throwing an exception.

    - class SomeClass { +

    + A destructor should perform the same way whether or not there is an active exception. Typically, this means that it should invoke only operations that do not throw exceptions, or it should handle all exceptions and not rethrow them (even implicitly). This compliant solution differs from the previous noncompliant code example by having an explicit + + return + + statement in the + + SomeClass + + destructor. This statement prevents control from reaching the end of the exception handler. Consequently, this handler will catch the exception thrown by + + Bad::~Bad() + + when + + bad_member + + is destroyed. It will also catch any exceptions thrown within the compound statement of the + + function-try-block + + , but the + + SomeClass + + destructor will not terminate by throwing an exception. +

    + + class SomeClass { Bad bad_member; public: ~SomeClass() @@ -95,23 +286,39 @@ public: // return statement will prevent that from happening. return; } -}; +}; +
    -

    In this noncompliant code example, a global deallocation is declared noexcept(false) and throws an exception if some conditions are not properly met. However, throwing from a deallocation function results in undefined behavior.

    - #include <stdexcept> - +

    + In this noncompliant code example, a global deallocation is declared + + noexcept(false) + + and throws an exception if some conditions are not properly met. However, throwing from a deallocation function results in + + undefined behavior + + . +

    + + #include <stdexcept> +ย  bool perform_dealloc(void *); - +ย  void operator delete(void *ptr) noexcept(false) { if (perform_dealloc(ptr)) { throw std::logic_error("Something bad"); } -} +} +
    -

    The compliant solution does not throw exceptions in the event the deallocation fails but instead fails as gracefully as possible.

    - #include <cstdlib> +

    + The compliant solution does not throw exceptions in the event the deallocation fails but instead fails as gracefully as possible. +

    + + #include <cstdlib> #include <stdexcept> bool perform_dealloc(void *); @@ -122,10 +329,17 @@ void operator delete(void *ptr) noexcept(true) { log_failure("Deallocation of pointer failed"); std::exit(1); // Fail, but still call destructors } -} +} +
    -

    Attempting to throw exceptions from destructors or deallocation functions can result in undefined behavior, leading to resource leaks or denial-of-service attacks.

    +

    + Attempting to throw exceptions from destructors or deallocation functions can result in undefined behavior, leading to resource leaks or + + denial-of-service attacks + + . +

    @@ -162,10 +376,14 @@ void operator delete(void *ptr) noexcept(true) { Medium @@ -198,7 +416,10 @@ void operator delete(void *ptr) noexcept(true) { 20.10 @@ -229,7 +452,9 @@ void operator delete(void *ptr) noexcept(true) { 2021.2 @@ -244,7 +469,9 @@ void operator delete(void *ptr) noexcept(true) { 2021.4 @@ -258,7 +485,9 @@ void operator delete(void *ptr) noexcept(true) { @@ -325,8 +566,12 @@ void operator delete(void *ptr) noexcept(true) { 20.10
    - P6 + + P6 + - L2 + + L2 +
    - destructor-without-noexceptdelete-without-noexcept + + destructor-without-noexcept + delete-without-noexcept + Fully checked @@ -214,7 +435,9 @@ void operator delete(void *ptr) noexcept(true) { 7.2.0 - CertC++-DCL57 + + CertC++-DCL57 + - C++2045, C++2047, C++4032, C++4631 + + C++2045, C++2047, C++4032, C++4631 + - MISRA.DTOR.THROW + + MISRA.DTOR.THROW + - 453 S + + 453 S + Partially implemented @@ -274,8 +503,12 @@ void operator delete(void *ptr) noexcept(true) { 2021.2 - CERT_CPP-DCL57-a - CERT_CPP-DCL57-b + + CERT_CPP-DCL57-a + + + CERT_CPP-DCL57-b + Never allow an exception to be thrown from a destructor, deallocation, and swap @@ -307,10 +540,18 @@ void operator delete(void *ptr) noexcept(true) { - 7.17 + 7.16 - V509, V1045 + + + V509 + + , + + V1045 + + - destructor-without-noexcept - delete-without-noexcept + + destructor-without-noexcept + + + delete-without-noexcept + Fully checked @@ -336,7 +581,17 @@ void operator delete(void *ptr) noexcept(true) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -421,7 +676,9 @@ void operator delete(void *ptr) noexcept(true) { diff --git a/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces-standard.qhelp b/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces-standard.qhelp index c2fd4c9a7a..8b30845686 100644 --- a/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces-standard.qhelp +++ b/cpp/cert/src/rules/DCL58-CPP/ModificationOfTheStandardNamespaces-standard.qhelp @@ -1,48 +1,229 @@
    -

    Namespaces introduce new declarative regions for declarations, reducing the likelihood of conflicting identifiers with other declarative regions. One feature of namespaces is that they can be further extended, even within separate translation units. For instance, the following declarations are well-formed.

    - namespace MyNamespace { +

    + Namespaces introduce new declarative regions for declarations, reducing the likelihood of conflicting identifiers with other declarative regions. One feature of namespaces is that they can be further extended, even within separate translation units. For instance, the following declarations are well-formed. +

    + + namespace MyNamespace { int length; } - +ย  namespace MyNamespace { int width; } - +ย  void f() { MyNamespace::length = MyNamespace::width = 12; -} -

    The standard library introduces the namespace std for standards-provided declarations such as std::string, std::vector, and std::for_each. However, it is undefined behavior to introduce new declarations in namespace std except under special circumstances. The C++ Standard, [namespace.std], paragraphs 1 and 2 [ISO/IEC 14882-2014], states the following:

    +} +
    +

    + The standard library introduces the namespace + + std + + for standards-provided declarations such as + + std::string + + , + + std::vector + + , and + + std::for_each + + . However, it is + + undefined behavior + + to introduce new declarations in namespace + + std + + except under special circumstances.ย The C++ Standard,ย [namespace.std], paragraphs 1 and 2 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    1 The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

    -

    2 The behavior of a C++ program is undefined if it declares

    -

    โ€” an explicit specialization of any member function of a standard library class template, orโ€” an explicit specialization of any member function template of a standard library class or class template, orโ€” an explicit or partial specialization of any member class template of a standard library class or class template.

    +

    + + 1 + + The behavior of a C++ย program is undefined if it adds declarations or definitions to namespace + + std + + or to aย namespace within namespace + + std + + unless otherwise specified. A program may add a template specializationย for any standard library template to namespace + + std + + only if the declaration depends on a user-defined typeย and the specialization meets the standard library requirements for the original template and is not explicitlyย prohibited. +

    +

    + + 2 + + The behavior of a C++ย program is undefined if it declares +

    +

    + โ€” an explicit specialization of any member function of a standard library class template, or + โ€” an explicit specialization of any member function template of a standard library class or class template,ย or + โ€” an explicit or partial specialization of any member class template of a standard library class or classย template. +

    -

    In addition to restricting extensions to the the namespace std, the C++ Standard, [namespace.posix], paragraph 1, further states the following:

    +

    + In addition to restricting extensions to the the namespace + + std + + , theย C++ Standard,ย [namespace.posix], paragraph 1, further states the following: +

    -

    The behavior of a C++ program is undefined if it adds declarations or definitions to namespace posix or to a namespace within namespace posix unless otherwise specified. The namespace posix is reserved for use by ISO/IEC 9945 and other POSIX standards.

    +

    + The behavior of a C++ย program is undefined if it adds declarations or definitions to namespace + + posix + + or toย a namespace within namespace + + posix + + unless otherwise specified. The namespace + + posix + + is reserved for useย by ISO/IEC 9945 and other POSIX standards. +

    -

    Do not add declarations or definitions to the standard namespaces std or posix, or to a namespace contained therein, except for a template specialization that depends on a user-defined type that meets the standard library requirements for the original template.

    -

    The Library Working Group, responsible for the wording of the Standard Library section of the C++ Standard, has an unresolved issue on the definition of user-defined type. Although the Library Working Group has no official stance on the definition [INCITS 2014], we define it to be any class, struct, union, or enum that is not defined within namespace std or a namespace contained within namespace std. Effectively, it is a user-provided type instead of a standard libraryโ€“provided type.

    +

    + Do not add declarations or definitions to the standard namespaces + + std + + or + + posix + + , or to a namespace contained therein, except for a template specialization that depends on a user-defined type that meets the standard library requirements for the original template. +

    +

    + The Library Working Group, responsible for the wording of the Standard Library section of the C++ Standard, has an unresolved + + issue + + on the definition of + + user-defined type + + . Although the Library Working Group has no official stance on the definition [ + + INCITS 2014 + + ], we define it to be any + + class + + , + + struct + + , + + union + + , or + + enum + + that is not defined within namespace + + std + + or a namespace contained within namespace + + std + + . Effectively, it is a user-provided type instead of a standard libraryโ€“provided type. +

    -

    In this noncompliant code example, the declaration of x is added to the namespace std, resulting in undefined behavior.

    - namespace std { +

    + In this noncompliant code example, the declaration of + + x + + is added to the namespace + + std + + , resulting in + + undefined behavior + + . +

    + + namespace std { int x; } - +
    -

    This compliant solution assumes the intention of the programmer was to place the declaration of x into a namespace to prevent collisions with other global identifiers. Instead of placing the declaration into the namespace std, the declaration is placed into a namespace without a reserved name.

    - namespace nonstd { +

    + This compliant solution assumes the intention of the programmer was to place the declaration of + + x + + into a namespace to prevent collisions with other global identifiers. Instead of placing the declaration into the namespace + + std + + , the declaration is placed into a namespace without a reserved name. +

    + + namespace nonstd { int x; } - +
    -

    In this noncompliant code example, a template specialization of std::plus is added to the namespace std in an attempt to allow std::plus to concatenate a std::string and MyString object. However, because the template specialization is of a standard libraryโ€“provided type (std::string), this code results in undefined behavior.

    - #include <functional> +

    + In this noncompliant code example, a template specialization of + + std::plus + + is added to the namespace + + std + + in an attempt to allow + + std::plus + + to concatenate a + + std::string + + and + + MyString + + object. However, because the template specialization is of a standard libraryโ€“provided type ( + + std::string + + ), this code results in undefined behavior. +

    + + #include <functional> #include <iostream> #include <string> @@ -71,11 +252,38 @@ void f() { std::cout << p(s1, s2) << std::endl; } - +
    -

    The interface for std::plus requires that both arguments to the function call operator and the return type are of the same type. Because the attempted specialization in the noncompliant code example results in undefined behavior, this compliant solution defines a new std::binary_function derivative that can add a std::string to a MyString object without requiring modification of the namespace std.

    - #include <functional> +

    + The interface for + + std::plus + + requires that both arguments to the function call operator and the return type are of the same type. Because the attempted specialization in the noncompliant code example results in + + undefined behavior + + , this compliant solution defines a new + + std::binary_function + + derivative that can add a + + std::string + + to a + + MyString + + object without requiring modification of the namespace + + std + + . +

    + + #include <functional> #include <iostream> #include <string> @@ -100,11 +308,31 @@ void f() { my_plus p; std::cout << p(s1, s2) << std::endl; -} +} +
    -

    In this compliant solution, a specialization of std::plus is added to the std namespace, but the specialization depends on a user-defined type and meets the Standard Template Library requirements for the original template, so it complies with this rule. However, because MyString can be constructed from std::string, this compliant solution involves invoking a converting constructor whereas the previous compliant solution does not.

    - #include <functional> +

    + In this compliant solution, a specialization of + + std::plus + + is added toย the + + std + + namespace, but the specialization depends on a user-defined type and meets the Standard Template Library requirements for the original template, so it complies with this rule. However, because + + MyString + + can be constructed from + + std::string + + , this compliant solution involves invoking a converting constructor whereas the previous compliant solution does not. +

    + + #include <functional> #include <iostream> #include <string> @@ -132,10 +360,17 @@ void f() { std::plus<MyString> p; std::cout << p(s1, s2).get_data() << std::endl; -} +} +
    -

    Altering the standard namespace can cause undefined behavior in the C++ standard library.

    +

    + Altering the standard namespace can cause + + undefined behavior + + in the C++ standard library. +

    "Never allow exceptions from escaping destructors or from an overloaded - operator delete() + + operator delete() + " (p. 29)
    @@ -172,10 +407,14 @@ void f() { Medium @@ -208,7 +447,9 @@ void f() { 7.2.0 @@ -223,7 +464,9 @@ void f() { 2021.2 @@ -238,7 +481,11 @@ void f() { 2021.4 @@ -253,7 +500,9 @@ void f() { 2021.2 @@ -299,10 +553,14 @@ void f() { @@ -317,7 +575,11 @@ void f() { 4.10 @@ -326,7 +588,17 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - CertC++-DCL58 + + CertC++-DCL58 + - C++3180, C++3181, C++3182 + + C++3180, C++3181, C++3182 + - CERT.DCL.STD_NS_MODIFIED + + + CERT.DCL.STD_NS_MODIFIED + + - CERT_CPP-DCL58-a + + CERT_CPP-DCL58-a + Do not modify the standard namespaces 'std' and 'posix' @@ -287,7 +536,12 @@ void f() { 4.4 - 4032, 4035, 4631 + + 4032, 4035, + + 4631 + + - 7.17 + 7.16 - V1061 + + + V1061 + + - S3470 + + + S3470 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -375,10 +647,14 @@ void f() { diff --git a/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile-standard.qhelp b/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile-standard.qhelp index ef3567af38..66798590f1 100644 --- a/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile-standard.qhelp +++ b/cpp/cert/src/rules/DCL59-CPP/UnnamedNamespaceInHeaderFile-standard.qhelp @@ -1,61 +1,136 @@
    -

    Unnamed namespaces are used to define a namespace that is unique to the translation unit, where the names contained within have internal linkage by default. The C++ Standard, [namespace.unnamed], paragraph 1 [ISO/IEC 14882-2014], states the following:

    +

    + Unnamed namespaces are used to define a namespace that is unique to the translation unit, where the names contained within have internal linkage by default. The C++ Standard,ย [namespace.unnamed], paragraph 1 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    An unnamed-namespace-definition behaves as if it were replaced by:

    -
      inline namespace unique { /* empty body */ }  using namespace unique ;  namespace unique { namespace-body }
    -

    where inline appears if and only if it appears in the unnamed-namespace-definition, all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the entire program.

    +

    + An + + unnamed-namespace-definition + + behaves as if it were replaced by: +

    +
      inlineย namespace unique { /* empty body */ }  using namespace unique ;  namespace unique { namespace-body }
    +

    + where + + inline + + appears if and only if it appears in the + + unnamed-namespace-definition + + , all occurrences of + + unique + + in a translation unit are replaced by the same identifier, and this identifier differs from all otherย identifiers in the entire program. +

    -

    Production-quality C++ code frequently uses header files as a means to share code between translation units. A header file is any file that is inserted into a translation unit through an #include directive. Do not define an unnamed namespace in a header file. When an unnamed namespace is defined in a header file, it can lead to surprising results. Due to default internal linkage, each translation unit will define its own unique instance of members of the unnamed namespace that are ODR-used within that translation unit. This can cause unexpected results, bloat the resulting executable, or inadvertently trigger undefined behavior due to one-definition rule (ODR) violations.

    +

    + Production-quality C++ code frequently uses + + header files + + as a means to share code between translation units. A header file is any file that is inserted into a translation unit through an + + #include + + directive. Do not define an unnamed namespace in a header file.ย When an unnamed namespace is defined in a header file, it can lead to surprising results.ย Due to default internal linkage, each translation unit will define its own unique instance of members of the unnamed namespace that are + + ODR-used + + within that translation unit. This can cause unexpected results, bloat the resulting executable, or inadvertently trigger + + undefined behavior + + due to one-definition rule (ODR) violations. +

    -

    In this noncompliant code example, the variable v is defined in an unnamed namespace within a header file and is accessed from two separate translation units. Each translation unit prints the current value of v and then assigns a new value into it. However, because v is defined within an unnamed namespace, each translation unit operates on its own instance of v, resulting in unexpected output.

    - // a.h +

    + In this noncompliant code example, the variable + + v + + is defined in an unnamed namespace within a header file and is accessed from two separate translation units. Each translation unit prints the current value of + + v + + and then assigns a new value into it. However, because + + v + + is defined within an unnamed namespace, each translation unit operates on its own instance of + + v + + , resulting in unexpected output. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE - +ย  namespace { int v; } - +ย  #endif // A_HEADER_FILE - +ย  // a.cpp #include "a.h" #include <iostream> - +ย  void f() { std::cout << "f(): " << v << std::endl; v = 42; // ... } - +ย  // b.cpp #include "a.h" #include <iostream> - +ย  void g() { std::cout << "g(): " << v << std::endl; v = 100; } - +ย  int main() { extern void f(); f(); // Prints v, sets it to 42 g(); // Prints v, sets it to 100 f(); g(); -} -

    When executed, this program prints the following.

    - f(): 0 +} + +

    + When executed, this program prints the following. +

    + + f(): 0 g(): 0 f(): 42 -g(): 100 +g(): 100 +
    -

    In this compliant solution, v is defined in only one translation unit but is externally visible to all translation units, resulting in the expected behavior.

    - // a.h +

    + In this compliant solution, + + v + + is defined in only one translation unit but is externally visible to all translation units, resulting in the expected behavior. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE @@ -90,50 +165,104 @@ int main() { g(); // Prints v, sets it to 100 f(); // Prints v, sets it back to 42 g(); // Prints v, sets it back to 100 -} -

    When executed, this program prints the following.

    - f(): 0 +} + +

    + When executed, this program prints the following. +

    + + f(): 0 g(): 42 f(): 100 -g(): 42 +g(): 42 +
    -

    In this noncompliant code example, the variable v is defined in an unnamed namespace within a header file, and an inline function, get_v(), is defined, which accesses that variable. ODR-using the inline function from multiple translation units (as shown in the implementation of f() and g()) violates the one-definition rule because the definition of get_v() is not identical in all translation units due to referencing a unique v in each translation unit.

    - // a.h +

    + In this noncompliant code example, the variable + + v + + is defined in an unnamed namespace within a header file, and an inline function, + + get_v() + + , is defined, which accesses that variable. ODR-using the inline function from multiple translation units (as shown in the implementation of + + f() + + and + + g() + + ) violates the + + one-definition rule + + because the definition of + + get_v() + + is not identical in all translation units due to referencing a unique + + v + + in each translation unit. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE - +ย  namespace { int v; } - +ย  inline int get_v() { return v; } - +ย  #endif // A_HEADER_FILE - +ย  // a.cpp #include "a.h" - +ย  void f() { int i = get_v(); // ... } - +ย  // b.cpp #include "a.h" - +ย  void g() { int i = get_v(); // ... -} -

    See DCL60-CPP. Obey the one-definition rule for more information on violations of the one-definition rule.

    +} +
    +

    + See + + DCL60-CPP. Obey the one-definition rule + + for more information on violations of the one-definition rule. +

    -

    In this compliant solution, v is defined in only one translation unit but is externally visible to all translation units and can be accessed from the inline get_v() function.

    - // a.h +

    + In this compliant solution, + + v + + is defined in only one translation unit but is externally visible to all translation units and can be accessed from the inline + + get_v() + + function. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE - +ย  extern int v; inline int get_v() { @@ -144,7 +273,7 @@ inline int get_v() { // a.cpp #include "a.h" - +ย  // Externally used by get_v(); int v; @@ -159,49 +288,85 @@ void f() { void g() { int i = get_v(); // ... -} +} +
    -

    In this noncompliant code example, the function f() is defined within a header file. However, including the header file in multiple translation units causes a violation of the one-definition rule that usually results in an error diagnostic generated at link time due to multiple definitions of a function with the same name.

    - // a.h +

    + In this noncompliant code example, the function + + f() + + is defined within a header file. However, including the header file in multiple translation units causes a violation of the one-definition rule that usually results in an error diagnostic generated at link time due to multiple definitions of a function with the same name. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE - +ย  void f() { /* ... */ } - +ย  #endif // A_HEADER_FILE - +ย  // a.cpp #include "a.h" // ... - +ย  // b.cpp #include "a.h" -// ... +// ... +
    -

    This noncompliant code example attempts to resolve the link-time errors by defining f() within an unnamed namespace. However, it produces multiple, unique definitions of f() in the resulting executable. If a.h is included from many translation units, it can lead to increased link times, a larger executable file, and reduced performance.

    - // a.h +

    + This noncompliant code example attempts to resolve the link-time errors by defining + + f() + + within an unnamed namespace. However, it produces multiple, unique definitions of + + f() + + in the resulting executable. If + + a.h + + is included from many translation units, it can lead to increased link times, a larger executable file, and reduced performance. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE - -namespace { +ย  +namespace {ย  void f() { /* ... */ } } - +ย  #endif // A_HEADER_FILE - +ย  // a.cpp #include "a.h" // ... - +ย  // b.cpp #include "a.h" -// ... +// ... +
    -

    In this compliant solution, f() is not defined with an unnamed namespace and is instead defined as an inline function. Inline functions are required to be defined identically in all the translation units in which they are used, which allows an implementation to generate only a single instance of the function at runtime in the event the body of the function does not get generated for each call site.

    - // a.h +

    + In this compliant solution, + + f() + + is not defined with an unnamed namespace and is instead defined as an inline function. Inline functions are required to be defined identically in all the translation units in which they are used, which allows an + + implementation + + to generate only a single instance of the function at runtime in the event the body of the function does not get generated for each call site. +

    + + // a.h #ifndef A_HEADER_FILE #define A_HEADER_FILE @@ -215,10 +380,17 @@ inline void f() { /* ... */ } // b.cpp #include "a.h" -// ... +// ... +
    -

    Defining an unnamed namespace within a header file can cause data integrity violations and performance problems but is unlikely to go unnoticed with sufficient testing. One-definition rule violations result in undefined behavior.

    +

    + Defining an unnamed namespace within a header file can cause data integrity violations and performance problems but is unlikely to go unnoticed with sufficient testing. One-definition rule violations result in + + undefined behavior + + . +

    Subclause 17.6.4.2.1, "Namespace - std + + std + " Subclause 17.6.4.2.2, "Namespace - posix + + posix + "
    @@ -255,16 +427,20 @@ inline void f() { /* ... */ } Medium
    - P4 + + P4 + - L3 + + L3 +
    -
    +
    @@ -291,7 +467,9 @@ inline void f() { /* ... */ } 20.10 @@ -322,27 +502,15 @@ inline void f() { /* ... */ } 3.9 - - - - - - @@ -355,7 +523,9 @@ inline void f() { /* ... */ } 2021.2 @@ -370,7 +540,9 @@ inline void f() { /* ... */ } 2021.4 @@ -384,7 +556,9 @@ inline void f() { /* ... */ } @@ -465,7 +647,9 @@ inline void f() { /* ... */ } 4.4 @@ -477,10 +661,14 @@ inline void f() { /* ... */ } @@ -489,7 +677,17 @@ inline void f() { /* ... */ }
    - unnamed-namespace-header + + unnamed-namespace-header + Fully checked @@ -307,7 +485,9 @@ inline void f() { /* ... */ } 7.2.0 - CertC++-DCL59 + + CertC++-DCL59 + - cert-dcl59-cpp + + cert-dcl59-cpp + Checked by - clang-tidy -
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.DECL.ANH - - Anonymous Namespace in Header File + + clang-tidy +
    - C++2518 + + C++2518 + - MISRA.NAMESPACE.UNMD + + MISRA.NAMESPACE.UNMD + - 286 S, 512 S + + 286 S, 512 S + Fully implemented @@ -400,7 +574,9 @@ inline void f() { /* ... */ } 2021.2 - CERT_CPP-DCL59-a + + CERT_CPP-DCL59-a + There shall be no unnamed namespaces in header files @@ -434,7 +610,9 @@ inline void f() { /* ... */ } 20.10 - unnamed-namespace-header + + unnamed-namespace-header + Fully checked @@ -450,7 +628,11 @@ inline void f() { /* ... */ } 4.10 - UnnamedNamespaceInHeader + + + UnnamedNamespaceInHeader + + - 2518 + + 2518 + - 7.17 + 7.16 - V1068 + + + V1068 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed-standard.qhelp b/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed-standard.qhelp index dec783194e..2bf3183369 100644 --- a/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed-standard.qhelp +++ b/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed-standard.qhelp @@ -1,46 +1,125 @@
    -

    Nontrivial C++ programs are generally divided into multiple translation units that are later linked together to form an executable. To support such a model, C++ restricts named object definitions to ensure that linking will behave deterministically by requiring a single definition for an object across all translation units. This model is called the one-definition rule (ODR), which is defined by the C++ Standard, [basic.def.odr], in paragraph 4 [ISO/IEC 14882-2014]:

    -

    Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly-defined. An inline function shall be defined in every translation unit in which it is odr-used.

    -

    The most common approach to multitranslation unit compilation involves declarations residing in a header file that is subsequently made available to a source file via #include. These declarations are often also definitions, such as class and function template definitions. This approach is allowed by an exception defined in paragraph 6, which, in part, states the following:

    +

    + Nontrivial C++ programs are generally divided into multiple translation units that are later linked together to form an executable. To support such a model, C++ restricts named object definitions to ensure that linking will behave deterministically by requiring a single definition for an object across all translation units. This model is called the o + + ne-definition rule + + (ODR), which is defined by the C++ Standard,ย [basic.def.odr], in paragraph 4ย [ + + ISO/IEC 14882-2014 + + ]: +

    +

    + Every program shall contain exactly one definition of every non-inline function or variable that is odr-usedย in that program; no diagnostic required. The definition can appear explicitly in the program, it can be foundย in the standard or a user-defined library, or (when appropriate) it is implicitly-defined. An inline function shall be defined in every translation unit in which it is odr-used. +

    +

    + The most common approach to multitranslation unit compilation involves declarations residing in a header file that is subsequently made available to a source file via + + #include + + . These declarations are often also definitions, such as class and function template definitions. This approach is allowed by an exception defined in paragraph 6, which, in part, states the following: +

    -

    There can be more than one definition of a class type, enumeration type, inline function with external linkage, class template, non-static function template, static data member of a class template, member function of a class template, or template specialization for which some template parameters are not specified in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements. Given such an entity named D defined in more than one translation unit....

    -

    If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

    +

    + There can be more than one definition of a class type, enumeration type, inline function withย external linkage, class template, non-static function template, static data memberย of a class template, member function of a class template, or template specialization forย which some template parameters are not specified in a program provided that each definitionย appears in a different translation unit, and provided the definitions satisfy the following requirements.ย Givenย such an entity named + + D + + defined in more than one translation unit.... +

    +

    + If the definitions of + + D + + satisfy all these requirements,ย then the program shall behave as if there were a single definition of + + D + + . If the definitions of + + D + + do not satisfyย these requirements, then the behavior is undefined. +

    -

    The requirements specified by paragraph 6 essentially state that that two definitions must be identical (not simply equivalent). Consequently, a definition introduced in two separate translation units by an #include directive generally will not violate the ODR because the definitions are identical in both translation units.

    -

    However, it is possible to violate the ODR of a definition introduced via #include using block language linkage specifications, vendor-specific language extensions, and so on. A more likely scenario for ODR violations is that accidental definitions of differing objects will exist in different translation units.

    -

    Do not violate the one-definition rule; violations result in undefined behavior.

    +

    + The requirements specified by paragraph 6 essentially state that that two definitions must be identical (not simply equivalent). Consequently, a definition introduced in two separate translation units by an + + #include + + directive generally will not violate the ODR because the definitions are identical in both translation units. +

    +

    + However, it is possible to violate the ODR of a definition introduced via + + #include + + using block language linkage specifications, vendor-specific language extensions, and so on. A more likely scenario for ODR violations is that accidental definitions of differing objects will exist in different translation units. +

    +

    + Do not violate the one-definition rule; violations result in + + undefined behavior + + . +

    -

    In this noncompliant code example, two different translation units define a class of the same name with differing definitions. Although the two definitions are functionally equivalent (they both define a class named S with a single, public, nonstatic data member int a), they are not defined using the same sequence of tokens. This code example violates the ODR and results in undefined behavior.

    - // a.cpp +

    + In this noncompliant code example, two different translation units define a class of the same name with differing definitions. Although the two definitions are functionally equivalent (they both define a class named + + S + + with a single, public, nonstatic data member + + int a + + ), they are not defined using the same sequence of tokens. This code example violates the ODR and results in + + undefined behavior + + . +

    + + // a.cpp struct S { int a; }; - +ย  // b.cpp class S { public: int a; -}; +}; +
    -

    The correct mitigation depends on programmer intent. If the programmer intends for the same class definition to be visible in both translation units because of common usage, the solution is to use a header file to introduce the object into both translation units, as shown in this compliant solution.

    - // S.h +

    + The correct mitigation depends on programmer intent. If the programmer intends for the same class definition to be visible in both translation units because of common usage, the solution is to use a header file to introduce the object into both translation units, as shown in this compliant solution. +

    + + // S.h struct S { int a; }; - +ย  // a.cpp #include "S.h" // b.cpp -#include "S.h" +#include "S.h" +
    -

    If the ODR violation was a result of accidental name collision, the best mitigation solution is to ensure that both class definitions are unique, as in this compliant solution.

    - // a.cpp +

    + If the ODR violation was a result of accidental name collision, the best mitigation solution is to ensure that both class definitions are unique, as in this compliant solution. +

    + + // a.cpp namespace { struct S { int a; @@ -53,43 +132,136 @@ class S { public: int a; }; -} -

    Alternatively, the classes could be given distinct names in each translation unit to avoid violating the ODR.

    +} +
    +

    + Alternatively, the classes could be given distinct names in each translation unit to avoid violating the ODR. +

    -

    In this noncompliant code example, a class definition is introduced into two translation units using #include. However, one of the translation units uses an implementation-defined #pragma that is supported by Microsoft Visual Studio to specify structure field alignment requirements. Consequently, the two class definitions may have differing layouts in each translation unit, which is a violation of the ODR.

    - // s.h +

    + In this noncompliant code example, a class definition is introduced into two translation units using + + #include + + . However, one of the translation units uses an + + implementation-defined + + + #pragma + + that is supported by Microsoft Visual Studio to specify structure field alignment requirements. Consequently, the two class definitions may have differing layouts in each translation unit, which is a violation of the ODR. +

    + + // s.h struct S { char c; int a; }; - +ย  void init_s(S &s); - +ย  // s.cpp #include "s.h" - +ย  void init_s(S &s); { s.c = 'a'; s.a = 12; } - +ย  // a.cpp #pragma pack(push, 1) #include "s.h" #pragma pack(pop) - +ย  void f() { S s; init_s(s); -} -

    Implementation Details

    -

    It is possible for the preceding noncompliant code example to result in a.cpp allocating space for an object with a different size than expected by init_s() in s.cpp. When translating s.cpp, the layout of the structure may include padding bytes between the c and a data members. When translating a.cpp, the layout of the structure may remove those padding bytes as a result of the #pragma pack directive, so the object passed to init_s() may be smaller than expected. Consequently, when init_s() initializes the data members of s, it may result in a buffer overrun.

    -

    For more information on the behavior of #pragma pack, see the vendor documentation for your implementation, such as Microsoft Visual Studio or GCC.

    +} +
    +

    + + Implementation Details + +

    +

    + It is possible for the preceding noncompliant code example to result in + + a.cpp + + allocating space for an object with a different size than expected by + + init_s() + + in + + s.cpp + + . When translating + + s.cpp + + , the layout of the structure may include padding bytes between the + + c + + and + + a + + data members. When translating + + a.cpp + + , the layout of the structure may remove those padding bytes as a result of the + + #pragma pack + + directive, so the object passed to + + init_s() + + may be smaller than expected. Consequently, when + + init_s() + + initializes the data members of + + s + + , it may result in a buffer overrun. +

    +

    + For more information on the behavior of + + #pragma pack + + , see the vendor documentation for your + + implementation + + , such as + + Microsoft Visual Studio + + or + + GCC + + . +

    -

    In this compliant solution, the implementation-defined structure member-alignment directive is removed, ensuring that all definitions of S comply with the ODR.

    - // s.h +

    + In this compliant solution, the implementation-defined structure member-alignment directive is removed, ensuring that all definitions of + + S + + comply with the ODR. +

    + + // s.h struct S { char c; int a; @@ -111,32 +283,146 @@ void init_s(S &s); { void f() { S s; init_s(s); -} +} +
    -

    In this noncompliant code example, the constant object n has internal linkage but is odr-used within f(), which has external linkage. Because f() is declared as an inline function, the definition of f() must be identical in all translation units. However, each translation unit has a unique instance of n, resulting in a violation of the ODR.

    - const int n = 42; - +

    + In this noncompliant code example, the constant object + + n + + has internal linkage but is + + odr-used + + within + + f() + + , which has external linkage. Because + + f() + + is declared as anย inline function, the definition of + + f() + + must be identical in all translation units. However, each translation unit has a unique instance of + + n + + , resulting in a violation of the ODR. +

    + + const int n = 42; +ย  int g(const int &lhs, const int &rhs); inline int f(int k) { return g(k, n); -} +} +
    -

    A compliant solution must change one of three factors: (1) it must not odr-use n within f(), (2) it must declare n such that it has external linkage, or (3) it must not use an inline definition of f().

    -

    If circumstances allow modification of the signature of g() to accept parameters by value instead of by reference, then n will not be odr-used within f() because n would then qualify as a constant expression. This solution is compliant but it is not ideal. It may not be possible (or desirable) to modify the signature of g(), such as if g() represented std::max() from <algorithm>. Also, because of the differing linkage used by n and f(), accidental violations of the ODR are still likely if the definition of f() is modified to odr-use n.

    - const int n = 42; - +

    + A compliant solution must change one of three factors: (1)ย it must not odr-use + + n + + within + + f() + + , (2)ย it must declare + + n + + such that it has external linkage, or (3) it must not use an inline definition of + + f() + + . +

    +

    + If circumstances allow modification of the signature of + + g() + + to accept parameters by value instead of by reference, then + + n + + will not be odr-used within + + f() + + because + + n + + would then qualify as a constant expression. This solution is compliant but it is not ideal. It may not be possible (or desirable) to modify the signature of + + g(), + + such as if + + g() + + represented + + std::max() + + from + + <algorithm> + + . Also, because of the differing linkage used by + + n + + and + + f() + + , accidental violations of the ODR are still likely if the definition of + + f() + + is modified to odr-use + + n + + . +

    + + const int n = 42; +ย  int g(int lhs, int rhs); inline int f(int k) { return g(k, n); -} +} +
    -

    In this compliant solution, the constant object n is replaced with an enumerator of the same name. Named enumerations defined at namespace scope have the same linkage as the namespace they are contained in. The global namespace has external linkage, so the definition of the named enumeration and its contained enumerators also have external linkage. Although less aesthetically pleasing, this compliant solution does not suffer from the same maintenance burdens of the previous code because n and f() have the same linkage.

    - enum Constants { +

    + In this compliant solution, the constant object + + n + + is replaced with an enumerator of the same name. Named enumerations defined at namespace scope have the same linkage as the namespace they are contained in. The global namespace has external linkage, so the definition of the named enumeration and its contained enumerators also have external linkage. Although less aesthetically pleasing, this compliant solution does not suffer from the same maintenance burdens of the previous code because + + n + + and + + f() + + have the same linkage. +

    + + enum Constants { N = 42 }; @@ -144,10 +430,32 @@ int g(const int &lhs, const int &rhs); inline int f(int k) { return g(k, N); -} +} +
    -

    Violating the ODR causes undefined behavior, which can result in exploits as well as denial-of-service attacks. As shown in "Support for Whole-Program Analysis and the Verification of the One-Definition Rule in C++" [Quinlan 06], failing to enforce the ODR enables a virtual function pointer attack known as the VPTR exploit. In this exploit, an object's virtual function table is corrupted so that calling a virtual function on the object results in malicious code being executed. See the paper by Quinlan and colleagues for more details. However, note that to introduce the malicious class, the attacker must have access to the system building the code.

    +

    + Violating the ODR causes + + undefined behavior + + , which can result in exploits as well as + + denial-of-service attacks + + .ย As shown inย "Support for Whole-Program Analysis and the Verification of the One-Definition Rule in C++" [ + + Quinlan 06 + + ], failing to enforce the ODR enables a virtual function pointer attack known as the + + VPTR + + exploit + + + . In this exploit, an object's virtual function table is corrupted so that calling a virtual function on the object results in malicious code being executed. See the paper by Quinlan and colleagues for more details.ย However, note that to introduce the malicious class,ย the attacker must have access to the system building the code. +

    @@ -184,10 +492,14 @@ inline int f(int k) { High @@ -220,7 +532,14 @@ inline int f(int k) { 20.10 @@ -248,10 +569,13 @@ inline int f(int k) { @@ -282,7 +608,9 @@ inline int f(int k) {
    - P3 + + P3 + - L3 + + L3 +
    - type-compatibilitydefinition-duplicateundefined-externundefined-extern-pure-virtualexternal-file-spreadingtype-file-spreading + + type-compatibility + definition-duplicate + undefined-extern + undefined-extern-pure-virtual + external-file-spreading + type-file-spreading + Partially checked @@ -236,7 +555,9 @@ inline int f(int k) { 7.2.0 - CertC++-DCL60 + + CertC++-DCL60 + - 6.2p0 + 6.1p0 - LANG.STRUCT.DEF.FDHLANG.STRUCT.DEF.ODH + + LANG.STRUCT.DEF.FDH + LANG.STRUCT.DEF.ODH + Function defined in header file @@ -268,7 +592,9 @@ inline int f(int k) { 2021.2 - C++1067, C++1509, C++1510 + + C++1067, C++1509, C++1510 + - 286 S, 287 S + + 286 S, 287 S + Fully implemented @@ -298,7 +626,9 @@ inline int f(int k) { 2021.2 - CERT_CPP-DCL60-a + + CERT_CPP-DCL60-a + A class, union or enum name (including qualification, if any) shall be a unique identifier @@ -332,12 +662,24 @@ inline int f(int k) { 20.10 - type-compatibility - definition-duplicate - undefined-extern - undefined-extern-pure-virtual - external-file-spreading - type-file-spreading + + type-compatibility + + + definition-duplicate + + + undefined-extern + + + undefined-extern-pure-virtual + + + external-file-spreading + + + type-file-spreading + Partially checked @@ -347,7 +689,17 @@ inline int f(int k) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql b/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql index 1717f18e30..7908609cc6 100644 --- a/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql +++ b/cpp/cert/src/rules/DCL60-CPP/OneDefinitionRuleNotObeyed.ql @@ -16,7 +16,5 @@ import codingstandards.cpp.cert import codingstandards.cpp.rules.onedefinitionruleviolation.OneDefinitionRuleViolation class OneDefinitionRuleNotObeyedQuery extends OneDefinitionRuleViolationSharedQuery { - OneDefinitionRuleNotObeyedQuery() { - this = ScopePackage::oneDefinitionRuleNotObeyedQuery() - } + OneDefinitionRuleNotObeyedQuery() { this = ScopePackage::oneDefinitionRuleNotObeyedQuery() } } diff --git a/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert-standard.qhelp b/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert-standard.qhelp index cdcf65adda..ddb56f87a3 100644 --- a/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert-standard.qhelp +++ b/cpp/cert/src/rules/ERR50-CPP/ConditionVariablePostConditionFailedCert-standard.qhelp @@ -1,57 +1,381 @@
    -

    The std::abort(), std::quick_exit(), and std::_Exit() functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit() and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is implementation-defined [ISO/IEC 9899:1999]. Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (See ERR50-CPP-EX1 for more information.)

    -

    The std::terminate() function calls the current terminate_handler function, which defaults to calling std::abort().

    -

    The C++ Standard defines several ways in which std::terminate() may be called implicitly by an implementation [ISO/IEC 14882-2014]:

    +

    + The + + std::abort() + + , + + std::quick_exit() + + , and + + std::_Exit() + + functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with + + std::atexit() + + and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is + + implementation-defined + + [ + + ISO/IEC 9899:1999 + + ].ย Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (Seeย ERR50-CPP-EX1 for more information.) +

    +

    + The + + std::terminate() + + function calls the current + + terminate_handler + + function, which defaults to calling + + std::abort() + + . +

    +

    + The C++ Standard defines several ways in which + + std::terminate() + + may be called implicitly by an + + implementation + + [ + + ISO/IEC 14882-2014 + + ]: +

      -
    1. When the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7)See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.
    2. -
    3. When a throw-expression with no operand attempts to rethrow an exception and no exception is being handled ([except.throw], paragraph 9)
    4. -
    5. When the exception handling mechanism cannot find a handler for a thrown exception ([except.handle], paragraph 9)See ERR51-CPP. Handle all exceptions for more information.
    6. -
    7. When the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec], paragraph 9)See ERR55-CPP. Honor exception specifications for more information.
    8. -
    9. When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    10. -
    11. When initialization of a nonlocal variable with static or thread storage duration exits via an exception ([basic.start.init], paragraph 6)See ERR58-CPP. Handle all exceptions thrown before main() begins executing for more information.
    12. -
    13. When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    14. -
    15. When execution of a function registered with std::atexit()or std::at_quick_exit() exits via an exception ([support.start.term], paragraphs 8 and 12)
    16. -
    17. When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) Note that std::unexpected() is currently deprecated.
    18. -
    19. When std::unexpected() throws an exception that is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception() is not included in that dynamic-exception-specification ([except.unexpected], paragraph 3)
    20. -
    21. When the function std::nested_exception::rethrow_nested() is called for an object that has captured no exception ([except.nested], paragraph 4)
    22. -
    23. When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5)See ERR51-CPP. Handle all exceptions for more information.
    24. -
    25. When the destructor is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.destr], paragraph 1)
    26. -
    27. When the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.assign], paragraph 1)
    28. -
    29. When calling condition_variable::wait(), condition_variable::wait_until(), or condition_variable::wait_for() results in a failure to meet the postcondition: lock.owns_lock() == true or lock.mutex() is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)
    30. -
    31. When calling condition_variable_any::wait(), condition_variable_any::wait_until(), or condition_variable_any::wait_for() results in a failure to meet the postcondition: lock is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22)
    32. +
    33. + When the exception handling mechanism, after completing the initialization of the exception objectย but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7) + See + + ERR60-CPP. Exception objects must be nothrow copy constructible + + for more information. +
    34. +
    35. + When a + + throw-expression + + with no operand attempts to rethrow an exception and no exception is beingย handled ([except.throw],ย paragraph 9) +
    36. +
    37. + When the exception handling mechanism cannot find a handler for a thrown exceptionย ([except.handle], paragraph 9) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    38. +
    39. + When the search for a handler encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception ([except.spec], paragraph 9) + See + + ERR55-CPP. Honor exception specifications + + for more information. +
    40. +
    41. + When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    42. +
    43. + When initialization of a nonlocal variable with static or thread storage durationย exits via anย exception ([basic.start.init], paragraph 6) + See + + ERR58-CPP. Handle all exceptions thrown before main() begins executing + + for more information. +
    44. +
    45. + When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    46. +
    47. + When execution of a function registered with + + std::atexit() + + or + + std::at_quick_exit() + + exits via an exception ([support.start.term], paragraphs 8 and 12) +
    48. +
    49. + When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) + Note that + + std::unexpected() + + is currently deprecated. +
    50. +
    51. + When + + std::unexpected() + + throws an exception that is not allowed by the previously violated + + dynamic-exception-specification + + , and + + std::bad_exception() + + is not included in that + + dynamic-exception-specification + + ([except.unexpected], paragraph 3) +
    52. +
    53. + When the function + + std::nested_exception::rethrow_nested() + + is called for an object that has capturedย no exception ([except.nested], paragraph 4) +
    54. +
    55. + When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    56. +
    57. + When the destructor is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.destr], paragraph 1) +
    58. +
    59. + When the copy assignment operator is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.assign], paragraph 1) +
    60. +
    61. + When calling + + condition_variable::wait() + + , + + condition_variable::wait_until() + + , or + + condition_variable::wait_for() + + results in a failure to meet the postcondition: + + lock.owns_lock() == true + + or + + lock.mutex() + + is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40) +
    62. +
    63. + When calling + + condition_variable_any::wait() + + , + + condition_variable_any::wait_until() + + , or + + condition_variable_any::wait_for() + + results in a failure to meet the postcondition: + + lock + + is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22) +
    -

    In many circumstances, the call stack will not be unwound in response to an implicit call to std::terminate(), and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:

    +

    + In many circumstances, the call stack will not be unwound in response to an implicit call to + + std::terminate() + + , and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard,ย [except.terminate], paragraph 2 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called.

    +

    + In the situation where no matching handler is found,ย it is implementation-defined whether or not the stack is unwound before + + std::terminate() + + is called. Inย the situation where the search for a handlerย encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception, it is implementation-defined whether theย stack is unwound, unwound partially, or not unwound at all before + + std::terminate() + + is called. In all otherย situations, the stack shall not be unwound before + + std::terminate() + + is called. +

    -

    Do not explicitly or implicitly call std::quick_exit(), std::abort(), or std::_Exit(). When the default terminate_handler is installed or the current terminate_handler responds by calling std::abort() or std::_Exit(), do not explicitly or implicitly call std::terminate(). Abnormal process termination is the typical vector for denial-of-service attacks.

    -

    The std::exit() function is more complex. The C++ Standard, [basic.start.main], paragraph 4, states:

    +

    + Do not explicitly or implicitly call + + std::quick_exit() + + , + + std::abort() + + , or + + std::_Exit() + + . When the default + + terminate_handler + + is installed or the current + + terminate_handler + + responds by calling + + std::abort() + + or + + std::_Exit() + + , do not explicitly or implicitly call + + std::terminate() + + . + + Abnormal process termination + + is the typical vector for + + denial-of-service attacks + + . +

    +

    + The + + std::exit() + + function is more complex. The C++ Standard, + [basic.start.main], paragraph 4, states: +

    -

    Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.

    +

    + Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior. +

    -

    You may call std::exit() only in a program that has not yet initialized any objects with automatic storage duration.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the call to f(), which was registered as an exit handler with std::at_exit(), may result in a call to std::terminate() because throwing_func() may throw an exception.

    - #include <cstdlib> - +

    + You may call + + std::exit() + + only in a program that has not yet initialized any objects with automatic storage duration. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the call to + + f() + + , which was registered as an exit handler with + + std::at_exit() + + , may result in a call to + + std::terminate() + + because + + throwing_func() + + may throw an exception. +

    + + #include <cstdlib> +ย  void throwing_func() noexcept(false); - +ย  void f() { // Not invoked by the program except as an exit handler. throwing_func(); } - +ย  int main() { if (0 != std::atexit(f)) { // Handle error } // ... -} +} +
    -

    In this compliant solution, f() handles all exceptions thrown by throwing_func() and does not rethrow.

    - #include <cstdlib> +

    + In this compliant solution, + + f() + + handles all exceptions thrown by + + throwing_func() + + and does not rethrow. +

    + + #include <cstdlib> void throwing_func() noexcept(false); @@ -68,34 +392,78 @@ int main() { // Handle error } // ... -} +} +
    -

    ERR50-CPP-EX1: It is acceptable, after indicating the nature of the problem to the operator, to explicitly call std::abort(), std::_Exit(), or std::terminate() in response to a critical program error for which no recovery is possible, as in this example.

    - #include <exception> +

    + + ERR50-CPP-EX1: + + It is acceptable, after indicating the nature of the problem to the operator, to explicitly call + + std::abort() + + , + + std::_Exit() + + , or + + std::terminate() + + in response to a critical program error for which no recovery is possible, as in this example. +

    + + #include <exception> void report(const char *msg) noexcept; [[noreturn]] void fast_fail(const char *msg) { // Report error message to operator report(msg); - +ย  // Terminate std::terminate(); } - +ย  void critical_function_that_fails() noexcept(false); - +ย  void f() { try { critical_function_that_fails(); } catch (...) { fast_fail("Critical function failure"); } -} -

    The assert() macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an implementation-defined manner before calling std::abort().

    +} +
    +

    + The + + assert() + + macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an + + implementation-defined + + manner before calling + + std::abort() + + . +

    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    @@ -132,10 +500,14 @@ void f() { Medium @@ -168,7 +540,9 @@ void f() { 20.10 @@ -216,8 +595,12 @@ void f() { 2021.4 @@ -231,7 +614,9 @@ void f() { @@ -318,10 +732,18 @@ void f() { @@ -336,7 +758,9 @@ void f() { 20.10 @@ -361,7 +789,17 @@ void f() {
    - P4 + + P4 + - L3 + + L3 +
    - stdlib-use + + stdlib-use + Partially checked @@ -181,10 +555,13 @@ void f() { - 6.2p0 + 6.1p0 - BADFUNC.ABORTBADFUNC.EXIT + + BADFUNC.ABORT + BADFUNC.EXIT + Use of abort @@ -201,7 +578,9 @@ void f() { 2021.2 - C++5014 + + C++5014 + - MISRA.TERMINATE - CERT.ERR.ABRUPT_TERM + + MISRA.TERMINATE + + + CERT.ERR.ABRUPT_TERM + - 122 S + + 122 S + Enhanced Enforcement @@ -247,19 +632,46 @@ void f() { 2021.2 - CERT_CPP-ERR50-a - CERT_CPP-ERR50-b - CERT_CPP-ERR50-c - CERT_CPP-ERR50-d - CERT_CPP-ERR50-e - CERT_CPP-ERR50-f - CERT_CPP-ERR50-g - CERT_CPP-ERR50-h - CERT_CPP-ERR50-i - CERT_CPP-ERR50-j - CERT_CPP-ERR50-k - CERT_CPP-ERR50-l - CERT_CPP-ERR50-mCERT_CPP-ERR50-n + + CERT_CPP-ERR50-a + + + CERT_CPP-ERR50-b + + + CERT_CPP-ERR50-c + + + CERT_CPP-ERR50-d + + + CERT_CPP-ERR50-e + + + CERT_CPP-ERR50-f + + + CERT_CPP-ERR50-g + + + CERT_CPP-ERR50-h + + + CERT_CPP-ERR50-i + + + CERT_CPP-ERR50-j + + + CERT_CPP-ERR50-k + + + CERT_CPP-ERR50-l + + + CERT_CPP-ERR50-m + CERT_CPP-ERR50-n + The execution of a function registered with 'std::atexit()' or 'std::at_quick_exit()' should not exit via an exception @@ -306,7 +718,9 @@ void f() { 4.4 - 5014 + + 5014 + - 7.17 + 7.16 - V667, V2014 + + + V667 + + , + + V2014 + + - stdlib-use + + stdlib-use + Partially checked @@ -352,7 +776,11 @@ void f() { 4.10 - S990 + + + S990 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -413,10 +851,14 @@ void f() { @@ -430,7 +872,9 @@ void f() { diff --git a/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert-standard.qhelp b/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert-standard.qhelp index cdcf65adda..ddb56f87a3 100644 --- a/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert-standard.qhelp +++ b/cpp/cert/src/rules/ERR50-CPP/ExitHandlerThrowsExceptionCert-standard.qhelp @@ -1,57 +1,381 @@
    -

    The std::abort(), std::quick_exit(), and std::_Exit() functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit() and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is implementation-defined [ISO/IEC 9899:1999]. Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (See ERR50-CPP-EX1 for more information.)

    -

    The std::terminate() function calls the current terminate_handler function, which defaults to calling std::abort().

    -

    The C++ Standard defines several ways in which std::terminate() may be called implicitly by an implementation [ISO/IEC 14882-2014]:

    +

    + The + + std::abort() + + , + + std::quick_exit() + + , and + + std::_Exit() + + functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with + + std::atexit() + + and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is + + implementation-defined + + [ + + ISO/IEC 9899:1999 + + ].ย Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (Seeย ERR50-CPP-EX1 for more information.) +

    +

    + The + + std::terminate() + + function calls the current + + terminate_handler + + function, which defaults to calling + + std::abort() + + . +

    +

    + The C++ Standard defines several ways in which + + std::terminate() + + may be called implicitly by an + + implementation + + [ + + ISO/IEC 14882-2014 + + ]: +

      -
    1. When the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7)See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.
    2. -
    3. When a throw-expression with no operand attempts to rethrow an exception and no exception is being handled ([except.throw], paragraph 9)
    4. -
    5. When the exception handling mechanism cannot find a handler for a thrown exception ([except.handle], paragraph 9)See ERR51-CPP. Handle all exceptions for more information.
    6. -
    7. When the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec], paragraph 9)See ERR55-CPP. Honor exception specifications for more information.
    8. -
    9. When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    10. -
    11. When initialization of a nonlocal variable with static or thread storage duration exits via an exception ([basic.start.init], paragraph 6)See ERR58-CPP. Handle all exceptions thrown before main() begins executing for more information.
    12. -
    13. When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    14. -
    15. When execution of a function registered with std::atexit()or std::at_quick_exit() exits via an exception ([support.start.term], paragraphs 8 and 12)
    16. -
    17. When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) Note that std::unexpected() is currently deprecated.
    18. -
    19. When std::unexpected() throws an exception that is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception() is not included in that dynamic-exception-specification ([except.unexpected], paragraph 3)
    20. -
    21. When the function std::nested_exception::rethrow_nested() is called for an object that has captured no exception ([except.nested], paragraph 4)
    22. -
    23. When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5)See ERR51-CPP. Handle all exceptions for more information.
    24. -
    25. When the destructor is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.destr], paragraph 1)
    26. -
    27. When the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.assign], paragraph 1)
    28. -
    29. When calling condition_variable::wait(), condition_variable::wait_until(), or condition_variable::wait_for() results in a failure to meet the postcondition: lock.owns_lock() == true or lock.mutex() is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)
    30. -
    31. When calling condition_variable_any::wait(), condition_variable_any::wait_until(), or condition_variable_any::wait_for() results in a failure to meet the postcondition: lock is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22)
    32. +
    33. + When the exception handling mechanism, after completing the initialization of the exception objectย but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7) + See + + ERR60-CPP. Exception objects must be nothrow copy constructible + + for more information. +
    34. +
    35. + When a + + throw-expression + + with no operand attempts to rethrow an exception and no exception is beingย handled ([except.throw],ย paragraph 9) +
    36. +
    37. + When the exception handling mechanism cannot find a handler for a thrown exceptionย ([except.handle], paragraph 9) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    38. +
    39. + When the search for a handler encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception ([except.spec], paragraph 9) + See + + ERR55-CPP. Honor exception specifications + + for more information. +
    40. +
    41. + When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    42. +
    43. + When initialization of a nonlocal variable with static or thread storage durationย exits via anย exception ([basic.start.init], paragraph 6) + See + + ERR58-CPP. Handle all exceptions thrown before main() begins executing + + for more information. +
    44. +
    45. + When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    46. +
    47. + When execution of a function registered with + + std::atexit() + + or + + std::at_quick_exit() + + exits via an exception ([support.start.term], paragraphs 8 and 12) +
    48. +
    49. + When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) + Note that + + std::unexpected() + + is currently deprecated. +
    50. +
    51. + When + + std::unexpected() + + throws an exception that is not allowed by the previously violated + + dynamic-exception-specification + + , and + + std::bad_exception() + + is not included in that + + dynamic-exception-specification + + ([except.unexpected], paragraph 3) +
    52. +
    53. + When the function + + std::nested_exception::rethrow_nested() + + is called for an object that has capturedย no exception ([except.nested], paragraph 4) +
    54. +
    55. + When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    56. +
    57. + When the destructor is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.destr], paragraph 1) +
    58. +
    59. + When the copy assignment operator is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.assign], paragraph 1) +
    60. +
    61. + When calling + + condition_variable::wait() + + , + + condition_variable::wait_until() + + , or + + condition_variable::wait_for() + + results in a failure to meet the postcondition: + + lock.owns_lock() == true + + or + + lock.mutex() + + is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40) +
    62. +
    63. + When calling + + condition_variable_any::wait() + + , + + condition_variable_any::wait_until() + + , or + + condition_variable_any::wait_for() + + results in a failure to meet the postcondition: + + lock + + is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22) +
    -

    In many circumstances, the call stack will not be unwound in response to an implicit call to std::terminate(), and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:

    +

    + In many circumstances, the call stack will not be unwound in response to an implicit call to + + std::terminate() + + , and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard,ย [except.terminate], paragraph 2 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called.

    +

    + In the situation where no matching handler is found,ย it is implementation-defined whether or not the stack is unwound before + + std::terminate() + + is called. Inย the situation where the search for a handlerย encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception, it is implementation-defined whether theย stack is unwound, unwound partially, or not unwound at all before + + std::terminate() + + is called. In all otherย situations, the stack shall not be unwound before + + std::terminate() + + is called. +

    -

    Do not explicitly or implicitly call std::quick_exit(), std::abort(), or std::_Exit(). When the default terminate_handler is installed or the current terminate_handler responds by calling std::abort() or std::_Exit(), do not explicitly or implicitly call std::terminate(). Abnormal process termination is the typical vector for denial-of-service attacks.

    -

    The std::exit() function is more complex. The C++ Standard, [basic.start.main], paragraph 4, states:

    +

    + Do not explicitly or implicitly call + + std::quick_exit() + + , + + std::abort() + + , or + + std::_Exit() + + . When the default + + terminate_handler + + is installed or the current + + terminate_handler + + responds by calling + + std::abort() + + or + + std::_Exit() + + , do not explicitly or implicitly call + + std::terminate() + + . + + Abnormal process termination + + is the typical vector for + + denial-of-service attacks + + . +

    +

    + The + + std::exit() + + function is more complex. The C++ Standard, + [basic.start.main], paragraph 4, states: +

    -

    Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.

    +

    + Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior. +

    -

    You may call std::exit() only in a program that has not yet initialized any objects with automatic storage duration.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the call to f(), which was registered as an exit handler with std::at_exit(), may result in a call to std::terminate() because throwing_func() may throw an exception.

    - #include <cstdlib> - +

    + You may call + + std::exit() + + only in a program that has not yet initialized any objects with automatic storage duration. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the call to + + f() + + , which was registered as an exit handler with + + std::at_exit() + + , may result in a call to + + std::terminate() + + because + + throwing_func() + + may throw an exception. +

    + + #include <cstdlib> +ย  void throwing_func() noexcept(false); - +ย  void f() { // Not invoked by the program except as an exit handler. throwing_func(); } - +ย  int main() { if (0 != std::atexit(f)) { // Handle error } // ... -} +} +
    -

    In this compliant solution, f() handles all exceptions thrown by throwing_func() and does not rethrow.

    - #include <cstdlib> +

    + In this compliant solution, + + f() + + handles all exceptions thrown by + + throwing_func() + + and does not rethrow. +

    + + #include <cstdlib> void throwing_func() noexcept(false); @@ -68,34 +392,78 @@ int main() { // Handle error } // ... -} +} +
    -

    ERR50-CPP-EX1: It is acceptable, after indicating the nature of the problem to the operator, to explicitly call std::abort(), std::_Exit(), or std::terminate() in response to a critical program error for which no recovery is possible, as in this example.

    - #include <exception> +

    + + ERR50-CPP-EX1: + + It is acceptable, after indicating the nature of the problem to the operator, to explicitly call + + std::abort() + + , + + std::_Exit() + + , or + + std::terminate() + + in response to a critical program error for which no recovery is possible, as in this example. +

    + + #include <exception> void report(const char *msg) noexcept; [[noreturn]] void fast_fail(const char *msg) { // Report error message to operator report(msg); - +ย  // Terminate std::terminate(); } - +ย  void critical_function_that_fails() noexcept(false); - +ย  void f() { try { critical_function_that_fails(); } catch (...) { fast_fail("Critical function failure"); } -} -

    The assert() macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an implementation-defined manner before calling std::abort().

    +} +
    +

    + The + + assert() + + macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an + + implementation-defined + + manner before calling + + std::abort() + + . +

    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    Subclause 7.20.4.1, "The - abort + + abort + Function" Subclause 7.20.4.4, "The - _Exit + + _Exit + Function"
    Subclause 15.5.1, "The - std::terminate() + + std::terminate() + Function" Subclause 18.5, "Start and Termination"
    @@ -132,10 +500,14 @@ void f() { Medium @@ -168,7 +540,9 @@ void f() { 20.10 @@ -216,8 +595,12 @@ void f() { 2021.4 @@ -231,7 +614,9 @@ void f() { @@ -318,10 +732,18 @@ void f() { @@ -336,7 +758,9 @@ void f() { 20.10 @@ -361,7 +789,17 @@ void f() {
    - P4 + + P4 + - L3 + + L3 +
    - stdlib-use + + stdlib-use + Partially checked @@ -181,10 +555,13 @@ void f() { - 6.2p0 + 6.1p0 - BADFUNC.ABORTBADFUNC.EXIT + + BADFUNC.ABORT + BADFUNC.EXIT + Use of abort @@ -201,7 +578,9 @@ void f() { 2021.2 - C++5014 + + C++5014 + - MISRA.TERMINATE - CERT.ERR.ABRUPT_TERM + + MISRA.TERMINATE + + + CERT.ERR.ABRUPT_TERM + - 122 S + + 122 S + Enhanced Enforcement @@ -247,19 +632,46 @@ void f() { 2021.2 - CERT_CPP-ERR50-a - CERT_CPP-ERR50-b - CERT_CPP-ERR50-c - CERT_CPP-ERR50-d - CERT_CPP-ERR50-e - CERT_CPP-ERR50-f - CERT_CPP-ERR50-g - CERT_CPP-ERR50-h - CERT_CPP-ERR50-i - CERT_CPP-ERR50-j - CERT_CPP-ERR50-k - CERT_CPP-ERR50-l - CERT_CPP-ERR50-mCERT_CPP-ERR50-n + + CERT_CPP-ERR50-a + + + CERT_CPP-ERR50-b + + + CERT_CPP-ERR50-c + + + CERT_CPP-ERR50-d + + + CERT_CPP-ERR50-e + + + CERT_CPP-ERR50-f + + + CERT_CPP-ERR50-g + + + CERT_CPP-ERR50-h + + + CERT_CPP-ERR50-i + + + CERT_CPP-ERR50-j + + + CERT_CPP-ERR50-k + + + CERT_CPP-ERR50-l + + + CERT_CPP-ERR50-m + CERT_CPP-ERR50-n + The execution of a function registered with 'std::atexit()' or 'std::at_quick_exit()' should not exit via an exception @@ -306,7 +718,9 @@ void f() { 4.4 - 5014 + + 5014 + - 7.17 + 7.16 - V667, V2014 + + + V667 + + , + + V2014 + + - stdlib-use + + stdlib-use + Partially checked @@ -352,7 +776,11 @@ void f() { 4.10 - S990 + + + S990 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -413,10 +851,14 @@ void f() { @@ -430,7 +872,9 @@ void f() { diff --git a/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert-standard.qhelp b/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert-standard.qhelp index cdcf65adda..ddb56f87a3 100644 --- a/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert-standard.qhelp +++ b/cpp/cert/src/rules/ERR50-CPP/ExplicitAbruptTerminationCert-standard.qhelp @@ -1,57 +1,381 @@
    -

    The std::abort(), std::quick_exit(), and std::_Exit() functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit() and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is implementation-defined [ISO/IEC 9899:1999]. Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (See ERR50-CPP-EX1 for more information.)

    -

    The std::terminate() function calls the current terminate_handler function, which defaults to calling std::abort().

    -

    The C++ Standard defines several ways in which std::terminate() may be called implicitly by an implementation [ISO/IEC 14882-2014]:

    +

    + The + + std::abort() + + , + + std::quick_exit() + + , and + + std::_Exit() + + functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with + + std::atexit() + + and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is + + implementation-defined + + [ + + ISO/IEC 9899:1999 + + ].ย Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (Seeย ERR50-CPP-EX1 for more information.) +

    +

    + The + + std::terminate() + + function calls the current + + terminate_handler + + function, which defaults to calling + + std::abort() + + . +

    +

    + The C++ Standard defines several ways in which + + std::terminate() + + may be called implicitly by an + + implementation + + [ + + ISO/IEC 14882-2014 + + ]: +

      -
    1. When the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7)See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.
    2. -
    3. When a throw-expression with no operand attempts to rethrow an exception and no exception is being handled ([except.throw], paragraph 9)
    4. -
    5. When the exception handling mechanism cannot find a handler for a thrown exception ([except.handle], paragraph 9)See ERR51-CPP. Handle all exceptions for more information.
    6. -
    7. When the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec], paragraph 9)See ERR55-CPP. Honor exception specifications for more information.
    8. -
    9. When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    10. -
    11. When initialization of a nonlocal variable with static or thread storage duration exits via an exception ([basic.start.init], paragraph 6)See ERR58-CPP. Handle all exceptions thrown before main() begins executing for more information.
    12. -
    13. When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    14. -
    15. When execution of a function registered with std::atexit()or std::at_quick_exit() exits via an exception ([support.start.term], paragraphs 8 and 12)
    16. -
    17. When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) Note that std::unexpected() is currently deprecated.
    18. -
    19. When std::unexpected() throws an exception that is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception() is not included in that dynamic-exception-specification ([except.unexpected], paragraph 3)
    20. -
    21. When the function std::nested_exception::rethrow_nested() is called for an object that has captured no exception ([except.nested], paragraph 4)
    22. -
    23. When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5)See ERR51-CPP. Handle all exceptions for more information.
    24. -
    25. When the destructor is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.destr], paragraph 1)
    26. -
    27. When the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.assign], paragraph 1)
    28. -
    29. When calling condition_variable::wait(), condition_variable::wait_until(), or condition_variable::wait_for() results in a failure to meet the postcondition: lock.owns_lock() == true or lock.mutex() is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)
    30. -
    31. When calling condition_variable_any::wait(), condition_variable_any::wait_until(), or condition_variable_any::wait_for() results in a failure to meet the postcondition: lock is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22)
    32. +
    33. + When the exception handling mechanism, after completing the initialization of the exception objectย but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7) + See + + ERR60-CPP. Exception objects must be nothrow copy constructible + + for more information. +
    34. +
    35. + When a + + throw-expression + + with no operand attempts to rethrow an exception and no exception is beingย handled ([except.throw],ย paragraph 9) +
    36. +
    37. + When the exception handling mechanism cannot find a handler for a thrown exceptionย ([except.handle], paragraph 9) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    38. +
    39. + When the search for a handler encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception ([except.spec], paragraph 9) + See + + ERR55-CPP. Honor exception specifications + + for more information. +
    40. +
    41. + When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    42. +
    43. + When initialization of a nonlocal variable with static or thread storage durationย exits via anย exception ([basic.start.init], paragraph 6) + See + + ERR58-CPP. Handle all exceptions thrown before main() begins executing + + for more information. +
    44. +
    45. + When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    46. +
    47. + When execution of a function registered with + + std::atexit() + + or + + std::at_quick_exit() + + exits via an exception ([support.start.term], paragraphs 8 and 12) +
    48. +
    49. + When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) + Note that + + std::unexpected() + + is currently deprecated. +
    50. +
    51. + When + + std::unexpected() + + throws an exception that is not allowed by the previously violated + + dynamic-exception-specification + + , and + + std::bad_exception() + + is not included in that + + dynamic-exception-specification + + ([except.unexpected], paragraph 3) +
    52. +
    53. + When the function + + std::nested_exception::rethrow_nested() + + is called for an object that has capturedย no exception ([except.nested], paragraph 4) +
    54. +
    55. + When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    56. +
    57. + When the destructor is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.destr], paragraph 1) +
    58. +
    59. + When the copy assignment operator is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.assign], paragraph 1) +
    60. +
    61. + When calling + + condition_variable::wait() + + , + + condition_variable::wait_until() + + , or + + condition_variable::wait_for() + + results in a failure to meet the postcondition: + + lock.owns_lock() == true + + or + + lock.mutex() + + is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40) +
    62. +
    63. + When calling + + condition_variable_any::wait() + + , + + condition_variable_any::wait_until() + + , or + + condition_variable_any::wait_for() + + results in a failure to meet the postcondition: + + lock + + is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22) +
    -

    In many circumstances, the call stack will not be unwound in response to an implicit call to std::terminate(), and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:

    +

    + In many circumstances, the call stack will not be unwound in response to an implicit call to + + std::terminate() + + , and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard,ย [except.terminate], paragraph 2 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called.

    +

    + In the situation where no matching handler is found,ย it is implementation-defined whether or not the stack is unwound before + + std::terminate() + + is called. Inย the situation where the search for a handlerย encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception, it is implementation-defined whether theย stack is unwound, unwound partially, or not unwound at all before + + std::terminate() + + is called. In all otherย situations, the stack shall not be unwound before + + std::terminate() + + is called. +

    -

    Do not explicitly or implicitly call std::quick_exit(), std::abort(), or std::_Exit(). When the default terminate_handler is installed or the current terminate_handler responds by calling std::abort() or std::_Exit(), do not explicitly or implicitly call std::terminate(). Abnormal process termination is the typical vector for denial-of-service attacks.

    -

    The std::exit() function is more complex. The C++ Standard, [basic.start.main], paragraph 4, states:

    +

    + Do not explicitly or implicitly call + + std::quick_exit() + + , + + std::abort() + + , or + + std::_Exit() + + . When the default + + terminate_handler + + is installed or the current + + terminate_handler + + responds by calling + + std::abort() + + or + + std::_Exit() + + , do not explicitly or implicitly call + + std::terminate() + + . + + Abnormal process termination + + is the typical vector for + + denial-of-service attacks + + . +

    +

    + The + + std::exit() + + function is more complex. The C++ Standard, + [basic.start.main], paragraph 4, states: +

    -

    Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.

    +

    + Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior. +

    -

    You may call std::exit() only in a program that has not yet initialized any objects with automatic storage duration.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the call to f(), which was registered as an exit handler with std::at_exit(), may result in a call to std::terminate() because throwing_func() may throw an exception.

    - #include <cstdlib> - +

    + You may call + + std::exit() + + only in a program that has not yet initialized any objects with automatic storage duration. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the call to + + f() + + , which was registered as an exit handler with + + std::at_exit() + + , may result in a call to + + std::terminate() + + because + + throwing_func() + + may throw an exception. +

    + + #include <cstdlib> +ย  void throwing_func() noexcept(false); - +ย  void f() { // Not invoked by the program except as an exit handler. throwing_func(); } - +ย  int main() { if (0 != std::atexit(f)) { // Handle error } // ... -} +} +
    -

    In this compliant solution, f() handles all exceptions thrown by throwing_func() and does not rethrow.

    - #include <cstdlib> +

    + In this compliant solution, + + f() + + handles all exceptions thrown by + + throwing_func() + + and does not rethrow. +

    + + #include <cstdlib> void throwing_func() noexcept(false); @@ -68,34 +392,78 @@ int main() { // Handle error } // ... -} +} +
    -

    ERR50-CPP-EX1: It is acceptable, after indicating the nature of the problem to the operator, to explicitly call std::abort(), std::_Exit(), or std::terminate() in response to a critical program error for which no recovery is possible, as in this example.

    - #include <exception> +

    + + ERR50-CPP-EX1: + + It is acceptable, after indicating the nature of the problem to the operator, to explicitly call + + std::abort() + + , + + std::_Exit() + + , or + + std::terminate() + + in response to a critical program error for which no recovery is possible, as in this example. +

    + + #include <exception> void report(const char *msg) noexcept; [[noreturn]] void fast_fail(const char *msg) { // Report error message to operator report(msg); - +ย  // Terminate std::terminate(); } - +ย  void critical_function_that_fails() noexcept(false); - +ย  void f() { try { critical_function_that_fails(); } catch (...) { fast_fail("Critical function failure"); } -} -

    The assert() macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an implementation-defined manner before calling std::abort().

    +} +
    +

    + The + + assert() + + macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an + + implementation-defined + + manner before calling + + std::abort() + + . +

    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    Subclause 7.20.4.1, "The - abort + + abort + Function" Subclause 7.20.4.4, "The - _Exit + + _Exit + Function"
    Subclause 15.5.1, "The - std::terminate() + + std::terminate() + Function" Subclause 18.5, "Start and Termination"
    @@ -132,10 +500,14 @@ void f() { Medium @@ -168,7 +540,9 @@ void f() { 20.10 @@ -216,8 +595,12 @@ void f() { 2021.4 @@ -231,7 +614,9 @@ void f() { @@ -318,10 +732,18 @@ void f() { @@ -336,7 +758,9 @@ void f() { 20.10 @@ -361,7 +789,17 @@ void f() {
    - P4 + + P4 + - L3 + + L3 +
    - stdlib-use + + stdlib-use + Partially checked @@ -181,10 +555,13 @@ void f() { - 6.2p0 + 6.1p0 - BADFUNC.ABORTBADFUNC.EXIT + + BADFUNC.ABORT + BADFUNC.EXIT + Use of abort @@ -201,7 +578,9 @@ void f() { 2021.2 - C++5014 + + C++5014 + - MISRA.TERMINATE - CERT.ERR.ABRUPT_TERM + + MISRA.TERMINATE + + + CERT.ERR.ABRUPT_TERM + - 122 S + + 122 S + Enhanced Enforcement @@ -247,19 +632,46 @@ void f() { 2021.2 - CERT_CPP-ERR50-a - CERT_CPP-ERR50-b - CERT_CPP-ERR50-c - CERT_CPP-ERR50-d - CERT_CPP-ERR50-e - CERT_CPP-ERR50-f - CERT_CPP-ERR50-g - CERT_CPP-ERR50-h - CERT_CPP-ERR50-i - CERT_CPP-ERR50-j - CERT_CPP-ERR50-k - CERT_CPP-ERR50-l - CERT_CPP-ERR50-mCERT_CPP-ERR50-n + + CERT_CPP-ERR50-a + + + CERT_CPP-ERR50-b + + + CERT_CPP-ERR50-c + + + CERT_CPP-ERR50-d + + + CERT_CPP-ERR50-e + + + CERT_CPP-ERR50-f + + + CERT_CPP-ERR50-g + + + CERT_CPP-ERR50-h + + + CERT_CPP-ERR50-i + + + CERT_CPP-ERR50-j + + + CERT_CPP-ERR50-k + + + CERT_CPP-ERR50-l + + + CERT_CPP-ERR50-m + CERT_CPP-ERR50-n + The execution of a function registered with 'std::atexit()' or 'std::at_quick_exit()' should not exit via an exception @@ -306,7 +718,9 @@ void f() { 4.4 - 5014 + + 5014 + - 7.17 + 7.16 - V667, V2014 + + + V667 + + , + + V2014 + + - stdlib-use + + stdlib-use + Partially checked @@ -352,7 +776,11 @@ void f() { 4.10 - S990 + + + S990 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -413,10 +851,14 @@ void f() { @@ -430,7 +872,9 @@ void f() { diff --git a/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert-standard.qhelp b/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert-standard.qhelp index cdcf65adda..ddb56f87a3 100644 --- a/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert-standard.qhelp +++ b/cpp/cert/src/rules/ERR50-CPP/JoinableThreadCopiedOrDestroyedCert-standard.qhelp @@ -1,57 +1,381 @@
    -

    The std::abort(), std::quick_exit(), and std::_Exit() functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit() and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is implementation-defined [ISO/IEC 9899:1999]. Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (See ERR50-CPP-EX1 for more information.)

    -

    The std::terminate() function calls the current terminate_handler function, which defaults to calling std::abort().

    -

    The C++ Standard defines several ways in which std::terminate() may be called implicitly by an implementation [ISO/IEC 14882-2014]:

    +

    + The + + std::abort() + + , + + std::quick_exit() + + , and + + std::_Exit() + + functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with + + std::atexit() + + and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is + + implementation-defined + + [ + + ISO/IEC 9899:1999 + + ].ย Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (Seeย ERR50-CPP-EX1 for more information.) +

    +

    + The + + std::terminate() + + function calls the current + + terminate_handler + + function, which defaults to calling + + std::abort() + + . +

    +

    + The C++ Standard defines several ways in which + + std::terminate() + + may be called implicitly by an + + implementation + + [ + + ISO/IEC 14882-2014 + + ]: +

      -
    1. When the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7)See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.
    2. -
    3. When a throw-expression with no operand attempts to rethrow an exception and no exception is being handled ([except.throw], paragraph 9)
    4. -
    5. When the exception handling mechanism cannot find a handler for a thrown exception ([except.handle], paragraph 9)See ERR51-CPP. Handle all exceptions for more information.
    6. -
    7. When the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec], paragraph 9)See ERR55-CPP. Honor exception specifications for more information.
    8. -
    9. When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    10. -
    11. When initialization of a nonlocal variable with static or thread storage duration exits via an exception ([basic.start.init], paragraph 6)See ERR58-CPP. Handle all exceptions thrown before main() begins executing for more information.
    12. -
    13. When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    14. -
    15. When execution of a function registered with std::atexit()or std::at_quick_exit() exits via an exception ([support.start.term], paragraphs 8 and 12)
    16. -
    17. When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) Note that std::unexpected() is currently deprecated.
    18. -
    19. When std::unexpected() throws an exception that is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception() is not included in that dynamic-exception-specification ([except.unexpected], paragraph 3)
    20. -
    21. When the function std::nested_exception::rethrow_nested() is called for an object that has captured no exception ([except.nested], paragraph 4)
    22. -
    23. When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5)See ERR51-CPP. Handle all exceptions for more information.
    24. -
    25. When the destructor is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.destr], paragraph 1)
    26. -
    27. When the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.assign], paragraph 1)
    28. -
    29. When calling condition_variable::wait(), condition_variable::wait_until(), or condition_variable::wait_for() results in a failure to meet the postcondition: lock.owns_lock() == true or lock.mutex() is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)
    30. -
    31. When calling condition_variable_any::wait(), condition_variable_any::wait_until(), or condition_variable_any::wait_for() results in a failure to meet the postcondition: lock is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22)
    32. +
    33. + When the exception handling mechanism, after completing the initialization of the exception objectย but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7) + See + + ERR60-CPP. Exception objects must be nothrow copy constructible + + for more information. +
    34. +
    35. + When a + + throw-expression + + with no operand attempts to rethrow an exception and no exception is beingย handled ([except.throw],ย paragraph 9) +
    36. +
    37. + When the exception handling mechanism cannot find a handler for a thrown exceptionย ([except.handle], paragraph 9) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    38. +
    39. + When the search for a handler encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception ([except.spec], paragraph 9) + See + + ERR55-CPP. Honor exception specifications + + for more information. +
    40. +
    41. + When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    42. +
    43. + When initialization of a nonlocal variable with static or thread storage durationย exits via anย exception ([basic.start.init], paragraph 6) + See + + ERR58-CPP. Handle all exceptions thrown before main() begins executing + + for more information. +
    44. +
    45. + When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    46. +
    47. + When execution of a function registered with + + std::atexit() + + or + + std::at_quick_exit() + + exits via an exception ([support.start.term], paragraphs 8 and 12) +
    48. +
    49. + When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) + Note that + + std::unexpected() + + is currently deprecated. +
    50. +
    51. + When + + std::unexpected() + + throws an exception that is not allowed by the previously violated + + dynamic-exception-specification + + , and + + std::bad_exception() + + is not included in that + + dynamic-exception-specification + + ([except.unexpected], paragraph 3) +
    52. +
    53. + When the function + + std::nested_exception::rethrow_nested() + + is called for an object that has capturedย no exception ([except.nested], paragraph 4) +
    54. +
    55. + When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    56. +
    57. + When the destructor is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.destr], paragraph 1) +
    58. +
    59. + When the copy assignment operator is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.assign], paragraph 1) +
    60. +
    61. + When calling + + condition_variable::wait() + + , + + condition_variable::wait_until() + + , or + + condition_variable::wait_for() + + results in a failure to meet the postcondition: + + lock.owns_lock() == true + + or + + lock.mutex() + + is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40) +
    62. +
    63. + When calling + + condition_variable_any::wait() + + , + + condition_variable_any::wait_until() + + , or + + condition_variable_any::wait_for() + + results in a failure to meet the postcondition: + + lock + + is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22) +
    -

    In many circumstances, the call stack will not be unwound in response to an implicit call to std::terminate(), and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:

    +

    + In many circumstances, the call stack will not be unwound in response to an implicit call to + + std::terminate() + + , and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard,ย [except.terminate], paragraph 2 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called.

    +

    + In the situation where no matching handler is found,ย it is implementation-defined whether or not the stack is unwound before + + std::terminate() + + is called. Inย the situation where the search for a handlerย encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception, it is implementation-defined whether theย stack is unwound, unwound partially, or not unwound at all before + + std::terminate() + + is called. In all otherย situations, the stack shall not be unwound before + + std::terminate() + + is called. +

    -

    Do not explicitly or implicitly call std::quick_exit(), std::abort(), or std::_Exit(). When the default terminate_handler is installed or the current terminate_handler responds by calling std::abort() or std::_Exit(), do not explicitly or implicitly call std::terminate(). Abnormal process termination is the typical vector for denial-of-service attacks.

    -

    The std::exit() function is more complex. The C++ Standard, [basic.start.main], paragraph 4, states:

    +

    + Do not explicitly or implicitly call + + std::quick_exit() + + , + + std::abort() + + , or + + std::_Exit() + + . When the default + + terminate_handler + + is installed or the current + + terminate_handler + + responds by calling + + std::abort() + + or + + std::_Exit() + + , do not explicitly or implicitly call + + std::terminate() + + . + + Abnormal process termination + + is the typical vector for + + denial-of-service attacks + + . +

    +

    + The + + std::exit() + + function is more complex. The C++ Standard, + [basic.start.main], paragraph 4, states: +

    -

    Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.

    +

    + Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior. +

    -

    You may call std::exit() only in a program that has not yet initialized any objects with automatic storage duration.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the call to f(), which was registered as an exit handler with std::at_exit(), may result in a call to std::terminate() because throwing_func() may throw an exception.

    - #include <cstdlib> - +

    + You may call + + std::exit() + + only in a program that has not yet initialized any objects with automatic storage duration. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the call to + + f() + + , which was registered as an exit handler with + + std::at_exit() + + , may result in a call to + + std::terminate() + + because + + throwing_func() + + may throw an exception. +

    + + #include <cstdlib> +ย  void throwing_func() noexcept(false); - +ย  void f() { // Not invoked by the program except as an exit handler. throwing_func(); } - +ย  int main() { if (0 != std::atexit(f)) { // Handle error } // ... -} +} +
    -

    In this compliant solution, f() handles all exceptions thrown by throwing_func() and does not rethrow.

    - #include <cstdlib> +

    + In this compliant solution, + + f() + + handles all exceptions thrown by + + throwing_func() + + and does not rethrow. +

    + + #include <cstdlib> void throwing_func() noexcept(false); @@ -68,34 +392,78 @@ int main() { // Handle error } // ... -} +} +
    -

    ERR50-CPP-EX1: It is acceptable, after indicating the nature of the problem to the operator, to explicitly call std::abort(), std::_Exit(), or std::terminate() in response to a critical program error for which no recovery is possible, as in this example.

    - #include <exception> +

    + + ERR50-CPP-EX1: + + It is acceptable, after indicating the nature of the problem to the operator, to explicitly call + + std::abort() + + , + + std::_Exit() + + , or + + std::terminate() + + in response to a critical program error for which no recovery is possible, as in this example. +

    + + #include <exception> void report(const char *msg) noexcept; [[noreturn]] void fast_fail(const char *msg) { // Report error message to operator report(msg); - +ย  // Terminate std::terminate(); } - +ย  void critical_function_that_fails() noexcept(false); - +ย  void f() { try { critical_function_that_fails(); } catch (...) { fast_fail("Critical function failure"); } -} -

    The assert() macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an implementation-defined manner before calling std::abort().

    +} +
    +

    + The + + assert() + + macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an + + implementation-defined + + manner before calling + + std::abort() + + . +

    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    Subclause 7.20.4.1, "The - abort + + abort + Function" Subclause 7.20.4.4, "The - _Exit + + _Exit + Function"
    Subclause 15.5.1, "The - std::terminate() + + std::terminate() + Function" Subclause 18.5, "Start and Termination"
    @@ -132,10 +500,14 @@ void f() { Medium @@ -168,7 +540,9 @@ void f() { 20.10 @@ -216,8 +595,12 @@ void f() { 2021.4 @@ -231,7 +614,9 @@ void f() { @@ -318,10 +732,18 @@ void f() { @@ -336,7 +758,9 @@ void f() { 20.10 @@ -361,7 +789,17 @@ void f() {
    - P4 + + P4 + - L3 + + L3 +
    - stdlib-use + + stdlib-use + Partially checked @@ -181,10 +555,13 @@ void f() { - 6.2p0 + 6.1p0 - BADFUNC.ABORTBADFUNC.EXIT + + BADFUNC.ABORT + BADFUNC.EXIT + Use of abort @@ -201,7 +578,9 @@ void f() { 2021.2 - C++5014 + + C++5014 + - MISRA.TERMINATE - CERT.ERR.ABRUPT_TERM + + MISRA.TERMINATE + + + CERT.ERR.ABRUPT_TERM + - 122 S + + 122 S + Enhanced Enforcement @@ -247,19 +632,46 @@ void f() { 2021.2 - CERT_CPP-ERR50-a - CERT_CPP-ERR50-b - CERT_CPP-ERR50-c - CERT_CPP-ERR50-d - CERT_CPP-ERR50-e - CERT_CPP-ERR50-f - CERT_CPP-ERR50-g - CERT_CPP-ERR50-h - CERT_CPP-ERR50-i - CERT_CPP-ERR50-j - CERT_CPP-ERR50-k - CERT_CPP-ERR50-l - CERT_CPP-ERR50-mCERT_CPP-ERR50-n + + CERT_CPP-ERR50-a + + + CERT_CPP-ERR50-b + + + CERT_CPP-ERR50-c + + + CERT_CPP-ERR50-d + + + CERT_CPP-ERR50-e + + + CERT_CPP-ERR50-f + + + CERT_CPP-ERR50-g + + + CERT_CPP-ERR50-h + + + CERT_CPP-ERR50-i + + + CERT_CPP-ERR50-j + + + CERT_CPP-ERR50-k + + + CERT_CPP-ERR50-l + + + CERT_CPP-ERR50-m + CERT_CPP-ERR50-n + The execution of a function registered with 'std::atexit()' or 'std::at_quick_exit()' should not exit via an exception @@ -306,7 +718,9 @@ void f() { 4.4 - 5014 + + 5014 + - 7.17 + 7.16 - V667, V2014 + + + V667 + + , + + V2014 + + - stdlib-use + + stdlib-use + Partially checked @@ -352,7 +776,11 @@ void f() { 4.10 - S990 + + + S990 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -413,10 +851,14 @@ void f() { @@ -430,7 +872,9 @@ void f() { diff --git a/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert-standard.qhelp b/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert-standard.qhelp index cdcf65adda..ddb56f87a3 100644 --- a/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert-standard.qhelp +++ b/cpp/cert/src/rules/ERR50-CPP/RethrowNestedWithoutCaptureCert-standard.qhelp @@ -1,57 +1,381 @@
    -

    The std::abort(), std::quick_exit(), and std::_Exit() functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit() and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is implementation-defined [ISO/IEC 9899:1999]. Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (See ERR50-CPP-EX1 for more information.)

    -

    The std::terminate() function calls the current terminate_handler function, which defaults to calling std::abort().

    -

    The C++ Standard defines several ways in which std::terminate() may be called implicitly by an implementation [ISO/IEC 14882-2014]:

    +

    + The + + std::abort() + + , + + std::quick_exit() + + , and + + std::_Exit() + + functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with + + std::atexit() + + and without executing destructors for objects with automatic, thread, or static storage duration. How a system manages open streams when a program ends is + + implementation-defined + + [ + + ISO/IEC 9899:1999 + + ].ย Open streams with unwritten buffered data may or may not be flushed, open streams may or may not be closed, and temporary files may or may not be removed. Because these functions can leave external resources, such as files and network communications, in an indeterminate state, they should be called explicitly only in direct response to a critical error in the application. (Seeย ERR50-CPP-EX1 for more information.) +

    +

    + The + + std::terminate() + + function calls the current + + terminate_handler + + function, which defaults to calling + + std::abort() + + . +

    +

    + The C++ Standard defines several ways in which + + std::terminate() + + may be called implicitly by an + + implementation + + [ + + ISO/IEC 14882-2014 + + ]: +

      -
    1. When the exception handling mechanism, after completing the initialization of the exception object but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7)See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.
    2. -
    3. When a throw-expression with no operand attempts to rethrow an exception and no exception is being handled ([except.throw], paragraph 9)
    4. -
    5. When the exception handling mechanism cannot find a handler for a thrown exception ([except.handle], paragraph 9)See ERR51-CPP. Handle all exceptions for more information.
    6. -
    7. When the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception ([except.spec], paragraph 9)See ERR55-CPP. Honor exception specifications for more information.
    8. -
    9. When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    10. -
    11. When initialization of a nonlocal variable with static or thread storage duration exits via an exception ([basic.start.init], paragraph 6)See ERR58-CPP. Handle all exceptions thrown before main() begins executing for more information.
    12. -
    13. When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1)See DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions for more information.
    14. -
    15. When execution of a function registered with std::atexit()or std::at_quick_exit() exits via an exception ([support.start.term], paragraphs 8 and 12)
    16. -
    17. When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) Note that std::unexpected() is currently deprecated.
    18. -
    19. When std::unexpected() throws an exception that is not allowed by the previously violated dynamic-exception-specification, and std::bad_exception() is not included in that dynamic-exception-specification ([except.unexpected], paragraph 3)
    20. -
    21. When the function std::nested_exception::rethrow_nested() is called for an object that has captured no exception ([except.nested], paragraph 4)
    22. -
    23. When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5)See ERR51-CPP. Handle all exceptions for more information.
    24. -
    25. When the destructor is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.destr], paragraph 1)
    26. -
    27. When the copy assignment operator is invoked on an object of type std::thread that refers to a joinable thread ([thread.thread.assign], paragraph 1)
    28. -
    29. When calling condition_variable::wait(), condition_variable::wait_until(), or condition_variable::wait_for() results in a failure to meet the postcondition: lock.owns_lock() == true or lock.mutex() is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40)
    30. -
    31. When calling condition_variable_any::wait(), condition_variable_any::wait_until(), or condition_variable_any::wait_for() results in a failure to meet the postcondition: lock is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22)
    32. +
    33. + When the exception handling mechanism, after completing the initialization of the exception objectย but before activation of a handler for the exception, calls a function that exits via an exception ([except.throw], paragraph 7) + See + + ERR60-CPP. Exception objects must be nothrow copy constructible + + for more information. +
    34. +
    35. + When a + + throw-expression + + with no operand attempts to rethrow an exception and no exception is beingย handled ([except.throw],ย paragraph 9) +
    36. +
    37. + When the exception handling mechanism cannot find a handler for a thrown exceptionย ([except.handle], paragraph 9) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    38. +
    39. + When the search for a handler encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception ([except.spec], paragraph 9) + See + + ERR55-CPP. Honor exception specifications + + for more information. +
    40. +
    41. + When the destruction of an object during stack unwinding terminates by throwing an exception ([except.ctor], paragraph 3) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    42. +
    43. + When initialization of a nonlocal variable with static or thread storage durationย exits via anย exception ([basic.start.init], paragraph 6) + See + + ERR58-CPP. Handle all exceptions thrown before main() begins executing + + for more information. +
    44. +
    45. + When destruction of an object with static or thread storage duration exits via an exception ([basic.start.term], paragraph 1) + See + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + for more information. +
    46. +
    47. + When execution of a function registered with + + std::atexit() + + or + + std::at_quick_exit() + + exits via an exception ([support.start.term], paragraphs 8 and 12) +
    48. +
    49. + When the implementationโ€™s default unexpected exception handler is called ([except.unexpected], paragraph 2) + Note that + + std::unexpected() + + is currently deprecated. +
    50. +
    51. + When + + std::unexpected() + + throws an exception that is not allowed by the previously violated + + dynamic-exception-specification + + , and + + std::bad_exception() + + is not included in that + + dynamic-exception-specification + + ([except.unexpected], paragraph 3) +
    52. +
    53. + When the function + + std::nested_exception::rethrow_nested() + + is called for an object that has capturedย no exception ([except.nested], paragraph 4) +
    54. +
    55. + When execution of the initial function of a thread exits via an exception ([thread.thread.constr], paragraph 5) + See + + ERR51-CPP. Handle all exceptions + + for more information. +
    56. +
    57. + When the destructor is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.destr], paragraph 1) +
    58. +
    59. + When the copy assignment operator is invoked on an object of type + + std::thread + + that refers to a joinable thread ([thread.thread.assign], paragraph 1) +
    60. +
    61. + When calling + + condition_variable::wait() + + , + + condition_variable::wait_until() + + , or + + condition_variable::wait_for() + + results in a failure to meet the postcondition: + + lock.owns_lock() == true + + or + + lock.mutex() + + is not locked by the calling thread ([thread.condition.condvar], paragraphs 11, 16, 21, 28, 33, and 40) +
    62. +
    63. + When calling + + condition_variable_any::wait() + + , + + condition_variable_any::wait_until() + + , or + + condition_variable_any::wait_for() + + results in a failure to meet the postcondition: + + lock + + is not locked by the calling thread ([thread.condition.condvarany], paragraphs 11, 16, and 22) +
    -

    In many circumstances, the call stack will not be unwound in response to an implicit call to std::terminate(), and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard, [except.terminate], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:

    +

    + In many circumstances, the call stack will not be unwound in response to an implicit call to + + std::terminate() + + , and in a few cases, it is implementation-defined whether or not stack unwinding will occur. The C++ Standard,ย [except.terminate], paragraph 2 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called.

    +

    + In the situation where no matching handler is found,ย it is implementation-defined whether or not the stack is unwound before + + std::terminate() + + is called. Inย the situation where the search for a handlerย encounters the outermost block of a function with a + + noexcept-specification + + that does not allow the exception, it is implementation-defined whether theย stack is unwound, unwound partially, or not unwound at all before + + std::terminate() + + is called. In all otherย situations, the stack shall not be unwound before + + std::terminate() + + is called. +

    -

    Do not explicitly or implicitly call std::quick_exit(), std::abort(), or std::_Exit(). When the default terminate_handler is installed or the current terminate_handler responds by calling std::abort() or std::_Exit(), do not explicitly or implicitly call std::terminate(). Abnormal process termination is the typical vector for denial-of-service attacks.

    -

    The std::exit() function is more complex. The C++ Standard, [basic.start.main], paragraph 4, states:

    +

    + Do not explicitly or implicitly call + + std::quick_exit() + + , + + std::abort() + + , or + + std::_Exit() + + . When the default + + terminate_handler + + is installed or the current + + terminate_handler + + responds by calling + + std::abort() + + or + + std::_Exit() + + , do not explicitly or implicitly call + + std::terminate() + + . + + Abnormal process termination + + is the typical vector for + + denial-of-service attacks + + . +

    +

    + The + + std::exit() + + function is more complex. The C++ Standard, + [basic.start.main], paragraph 4, states: +

    -

    Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.

    +

    + Terminating the program without leaving the current block (e.g., by calling the function std::exit(int) (17.5)) does not destroy any objects with automatic storage duration (11.4.6). If std::exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior. +

    -

    You may call std::exit() only in a program that has not yet initialized any objects with automatic storage duration.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the call to f(), which was registered as an exit handler with std::at_exit(), may result in a call to std::terminate() because throwing_func() may throw an exception.

    - #include <cstdlib> - +

    + You may call + + std::exit() + + only in a program that has not yet initialized any objects with automatic storage duration. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the call to + + f() + + , which was registered as an exit handler with + + std::at_exit() + + , may result in a call to + + std::terminate() + + because + + throwing_func() + + may throw an exception. +

    + + #include <cstdlib> +ย  void throwing_func() noexcept(false); - +ย  void f() { // Not invoked by the program except as an exit handler. throwing_func(); } - +ย  int main() { if (0 != std::atexit(f)) { // Handle error } // ... -} +} +
    -

    In this compliant solution, f() handles all exceptions thrown by throwing_func() and does not rethrow.

    - #include <cstdlib> +

    + In this compliant solution, + + f() + + handles all exceptions thrown by + + throwing_func() + + and does not rethrow. +

    + + #include <cstdlib> void throwing_func() noexcept(false); @@ -68,34 +392,78 @@ int main() { // Handle error } // ... -} +} +
    -

    ERR50-CPP-EX1: It is acceptable, after indicating the nature of the problem to the operator, to explicitly call std::abort(), std::_Exit(), or std::terminate() in response to a critical program error for which no recovery is possible, as in this example.

    - #include <exception> +

    + + ERR50-CPP-EX1: + + It is acceptable, after indicating the nature of the problem to the operator, to explicitly call + + std::abort() + + , + + std::_Exit() + + , or + + std::terminate() + + in response to a critical program error for which no recovery is possible, as in this example. +

    + + #include <exception> void report(const char *msg) noexcept; [[noreturn]] void fast_fail(const char *msg) { // Report error message to operator report(msg); - +ย  // Terminate std::terminate(); } - +ย  void critical_function_that_fails() noexcept(false); - +ย  void f() { try { critical_function_that_fails(); } catch (...) { fast_fail("Critical function failure"); } -} -

    The assert() macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an implementation-defined manner before calling std::abort().

    +} +
    +

    + The + + assert() + + macro is permissible under this exception because failed assertions will notify the operator on the standard error stream in an + + implementation-defined + + manner before calling + + std::abort() + + . +

    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    Subclause 7.20.4.1, "The - abort + + abort + Function" Subclause 7.20.4.4, "The - _Exit + + _Exit + Function"
    Subclause 15.5.1, "The - std::terminate() + + std::terminate() + Function" Subclause 18.5, "Start and Termination"
    @@ -132,10 +500,14 @@ void f() { Medium @@ -168,7 +540,9 @@ void f() { 20.10 @@ -216,8 +595,12 @@ void f() { 2021.4 @@ -231,7 +614,9 @@ void f() { @@ -318,10 +732,18 @@ void f() { @@ -336,7 +758,9 @@ void f() { 20.10 @@ -361,7 +789,17 @@ void f() {
    - P4 + + P4 + - L3 + + L3 +
    - stdlib-use + + stdlib-use + Partially checked @@ -181,10 +555,13 @@ void f() { - 6.2p0 + 6.1p0 - BADFUNC.ABORTBADFUNC.EXIT + + BADFUNC.ABORT + BADFUNC.EXIT + Use of abort @@ -201,7 +578,9 @@ void f() { 2021.2 - C++5014 + + C++5014 + - MISRA.TERMINATE - CERT.ERR.ABRUPT_TERM + + MISRA.TERMINATE + + + CERT.ERR.ABRUPT_TERM + - 122 S + + 122 S + Enhanced Enforcement @@ -247,19 +632,46 @@ void f() { 2021.2 - CERT_CPP-ERR50-a - CERT_CPP-ERR50-b - CERT_CPP-ERR50-c - CERT_CPP-ERR50-d - CERT_CPP-ERR50-e - CERT_CPP-ERR50-f - CERT_CPP-ERR50-g - CERT_CPP-ERR50-h - CERT_CPP-ERR50-i - CERT_CPP-ERR50-j - CERT_CPP-ERR50-k - CERT_CPP-ERR50-l - CERT_CPP-ERR50-mCERT_CPP-ERR50-n + + CERT_CPP-ERR50-a + + + CERT_CPP-ERR50-b + + + CERT_CPP-ERR50-c + + + CERT_CPP-ERR50-d + + + CERT_CPP-ERR50-e + + + CERT_CPP-ERR50-f + + + CERT_CPP-ERR50-g + + + CERT_CPP-ERR50-h + + + CERT_CPP-ERR50-i + + + CERT_CPP-ERR50-j + + + CERT_CPP-ERR50-k + + + CERT_CPP-ERR50-l + + + CERT_CPP-ERR50-m + CERT_CPP-ERR50-n + The execution of a function registered with 'std::atexit()' or 'std::at_quick_exit()' should not exit via an exception @@ -306,7 +718,9 @@ void f() { 4.4 - 5014 + + 5014 + - 7.17 + 7.16 - V667, V2014 + + + V667 + + , + + V2014 + + - stdlib-use + + stdlib-use + Partially checked @@ -352,7 +776,11 @@ void f() { 4.10 - S990 + + + S990 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -413,10 +851,14 @@ void f() { @@ -430,7 +872,9 @@ void f() { diff --git a/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions-standard.qhelp b/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions-standard.qhelp index c875e96022..2c70cd0110 100644 --- a/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions-standard.qhelp +++ b/cpp/cert/src/rules/ERR51-CPP/HandleAllExceptions-standard.qhelp @@ -1,29 +1,122 @@
    -

    When an exception is thrown, control is transferred to the nearest handler with a type that matches the type of the exception thrown. If no matching handler is directly found within the handlers for a try block in which the exception is thrown, the search for a matching handler continues to dynamically search for handlers in the surrounding try blocks of the same thread. The C++ Standard, [except.handle], paragraph 9 [ISO/IEC 14882-2014], states the following:

    +

    + When an exception is thrown, control is transferred to the nearest handler with a type that matches the type of the exception thrown. If no matching handler is directly found within the handlers for a try block in which the exception is thrown, the search for a matching handler continues to dynamically search for handlers in the surrounding try blocks of the same thread. The C++ Standard, [except.handle], paragraph 9 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If no matching handler is found, the function std::terminate() is called; whether or not the stack is unwound before this call to std::terminate() is implementation-defined.

    +

    + If no matching handler is found, the function + + std::terminate() + + is called; whether or not the stack isย unwound before this call to + + std::terminate() + + is implementation-defined. +

    -

    The default terminate handler called by std::terminate() calls std::abort(), which abnormally terminates the process. When std::abort() is called, or if the implementation does not unwind the stack prior to calling std::terminate(), destructors for objects may not be called and external resources can be left in an indeterminate state. Abnormal process termination is the typical vector for denial-of-service attacks. For more information on implicitly calling std::terminate(), see ERR50-CPP. Do not abruptly terminate the program.

    -

    All exceptions thrown by an application must be caught by a matching exception handler. Even if the exception cannot be gracefully recovered from, using the matching exception handler ensures that the stack will be properly unwound and provides an opportunity to gracefully manage external resources before terminating the process.

    -

    As per ERR50-CPP-EX1, a program that encounters an unrecoverable exception may explicitly catch the exception and terminate, but it may not allow the exception to remain uncaught. One possible solution to comply with this rule, as well as with ERR50-CPP, is for the main() function to catch all exceptions. While this does not generally allow the application to recover from the exception gracefully, it does allow the application to terminate in a controlled fashion.

    +

    + The default terminate handler called by + + std::terminate() + + calls + + std::abort() + + , which + + abnormally terminates + + the process. When + + std::abort() + + is called, or if the + + implementation + + does not unwind the stack prior to calling + + std::terminate() + + , destructors for objects may not be called andย external resources can be left in an indeterminate state.ย Abnormal process termination is the typical vector for + + denial-of-service + + attacks. For more information on implicitly calling + + std::terminate() + + , see + + ERR50-CPP. Do not abruptly terminate the program + + . +

    +

    + All exceptions thrown by an application must be caught by a matching exception handler. Even if the exception cannot be gracefully recovered from, using the matching exception handler ensures that the stack will be properly unwound and provides an opportunity to gracefully manage external resources before terminating the process. +

    +

    + As per + + ERR50-CPP-EX1 + + , a program that encounters an unrecoverable exception may explicitly catch the exception and terminate, but it may not allow the exception to remain uncaught.ย One possible solution to comply with this rule, as well as with ERR50-CPP, is for the + + main() + + function to catch all exceptions. While this does not generally allow the application to recover from the exception gracefully, it does allow the application to terminate in a controlled fashion. +

    -

    In this noncompliant code example, neither f() nor main() catch exceptions thrown by throwing_func(). Because no matching handler can be found for the exception thrown, std::terminate() is called.

    - void throwing_func() noexcept(false); - +

    + In this noncompliant code example, neither + + f() + + nor + + main() + + catch exceptions thrown by + + throwing_func() + + . Because no matching handler can be found for the exception thrown, + + std::terminate() + + is called. +

    + + void throwing_func() noexcept(false); +ย  void f() { throwing_func(); } - +ย  int main() { f(); -} +} +
    -

    In this compliant solution, the main entry point handles all exceptions, which ensures that the stack is unwound up to the main() function and allows for graceful management of external resources.

    - void throwing_func() noexcept(false); +

    + In this compliant solution, the main entry pointย handles all exceptions, which ensures that the stack is unwound up to the + + main() + + function and allows for graceful management of external resources. +

    + + void throwing_func() noexcept(false); void f() { throwing_func(); @@ -35,26 +128,51 @@ int main() { } catch (...) { // Handle error } -} +} +
    -

    In this noncompliant code example, the thread entry point function thread_start() does not catch exceptions thrown by throwing_func(). If the initial thread function exits because an exception is thrown, std::terminate() is called.

    - #include <thread> +

    + In this noncompliant code example, the thread entry point function + + thread_start() + + does not catch exceptions thrown by + + throwing_func() + + . If the initial thread function exits because an exception is thrown, + + std::terminate() + + is called. +

    + + #include <thread> void throwing_func() noexcept(false); - +ย  void thread_start() { throwing_func(); } - +ย  void f() { std::thread t(thread_start); t.join(); -} +} +
    -

    In this compliant solution, the thread_start() handles all exceptions and does not rethrow, allowing the thread to terminate normally.

    - #include <thread> +

    + In this compliant solution, the + + thread_start() + + handles all exceptions and does not rethrow, allowing the thread to + terminate normally. +

    + + #include <thread> void throwing_func() noexcept(false); @@ -69,10 +187,21 @@ void thread_start(void) { void f() { std::thread t(thread_start); t.join(); -} +} +
    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    Subclause 7.20.4.1, "The - abort + + abort + Function" Subclause 7.20.4.4, "The - _Exit + + _Exit + Function"
    Subclause 15.5.1, "The - std::terminate() + + std::terminate() + Function" Subclause 18.5, "Start and Termination"
    @@ -109,10 +238,14 @@ void f() { Medium @@ -145,7 +278,10 @@ void f() { 20.10 @@ -176,7 +314,9 @@ void f() { 2021.2 @@ -191,7 +331,9 @@ void f() { 2021.4 @@ -205,7 +347,9 @@ void f() { @@ -272,7 +422,12 @@ void f() { 20.10
    - P4 + + P4 + - L3 + + L3 +
    - main-function-catch-allearly-catch-all + + main-function-catch-all + early-catch-all + Partially checked @@ -161,7 +297,9 @@ void f() { 7.2.0 - CertC++-ERR51 + + CertC++-ERR51 + - C++4035, C++4036, C++4037 + + C++4035, C++4036, C++4037 + - MISRA.CATCH.ALL + + MISRA.CATCH.ALL + - 527 S + + 527 S + Partially implemented @@ -221,8 +365,12 @@ void f() { 2021.2 - CERT_CPP-ERR51-a - CERT_CPP-ERR51-b + + CERT_CPP-ERR51-a + + + CERT_CPP-ERR51-b + Always catch exceptions @@ -257,7 +405,9 @@ void f() { 4.4 - 4035, 4036, 4037 + + 4035, 4036, 4037 + - main-function-catch-allearly-catch-all + + + main-function-catch-all + early-catch-all + + Partially checked @@ -282,10 +437,30 @@ void f() {
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of ERR50-CPP. Do not abruptly terminate the program.

    +

    + + This rule is a subset of + + + + ERR50-CPP. Do not abruptly terminate the program + + + . +

    @@ -319,7 +494,9 @@ void f() { Subclause 15.1, "Throwing an Exception" Subclause 15.3, "Handling an Exception" Subclause 15.5.1, "The - std::terminate() + + std::terminate() + Function" diff --git a/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp-standard.qhelp b/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp-standard.qhelp index 516d16fcd9..a60c531bb1 100644 --- a/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp-standard.qhelp +++ b/cpp/cert/src/rules/ERR52-CPP/DoNotUseSetjmpOrLongjmp-standard.qhelp @@ -1,16 +1,113 @@
    -

    The C standard library facilities setjmp() and longjmp() can be used to simulate throwing and catching exceptions. However, these facilities bypass automatic resource management and can result in undefined behavior, commonly including resource leaks and denial-of-service attacks.

    -

    The C++ Standard, [support.runtime], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + The C standard library facilities + + setjmp() + + and + + longjmp() + + can be used to simulate throwing and catching exceptions. However, these facilities bypass automatic resource management and can result in + + undefined behavior + + , commonly including resource leaks and + + denial-of-service attacks + + . +

    +

    + The C++ Standard,ย [support.runtime], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ], states the following + : +

    -

    The function signature longjmp(jmp_buf jbuf, int val) has more restricted behavior in this International Standard. A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any automatic objects.

    +

    + The function signature + + longjmp(jmp_buf jbuf, int val) + + has more restricted behavior in this Internationalย Standard. A + + setjmp + + / + + longjmp + + call pair has undefined behavior if replacing the + + setjmp + + and + + longjmp + + by + + catch + + and + + throw + + would invoke any non-trivial destructors for any automatic objects. +

    -

    Do not call setjmp() or longjmp(); their usage can be replaced by more standard idioms such as throw expressions and catch statements.

    +

    + Do not call + + setjmp() + + or + + longjmp() + + ; their usage can be replaced by more standard idioms such as + + throw + + expressions and + + catch + + statements. +

    -

    If a throw expression would cause a nontrivial destructor to be invoked, then calling longjmp() in the same context will result in undefined behavior. In the following noncompliant code example, the call to longjmp() occurs in a context with a local Counter object. Since this objectโ€™s destructor is nontrivial, undefined behavior results.

    - #include <csetjmp> +

    + If a + + throw + + expression would cause a nontrivial destructor to be invoked, then calling + + longjmp() + + in the same context will result in + + undefined behavior + + . In the following noncompliant code example, the call to + + longjmp() + + occurs in a context with a local + + Counter + + object. Since this objectโ€™s destructor is nontrivial, undefined behavior results. +

    + + #include <csetjmp> #include <iostream> static jmp_buf env; @@ -38,17 +135,56 @@ int main() { } std::cout << "After longjmp(): Instances: " << Counter::instances << std::endl; } - -

    Implementation Details

    -

    The above code produces the following results when compiled with Clang 3.8 for Linux, demonstrating that the program, on this platform, fails to destroy the local Counter instance when the execution of f() is terminated. This is permissible as the behavior is undefined.

    - Before setjmp(): Instances: 0 + +

    + + Implementation Details + +

    +

    + The above code produces the following results when compiled with + + Clang + + 3.8 for Linux, demonstrating that the program, on this platform, fails to destroy the local + + Counter + + instance when the execution of + + f() + + is terminated. This is permissible as the behavior is undefined. +

    + + Before setjmp(): Instances: 0 f(): Instances: 1 From longjmp(): Instances: 1 -After longjmp(): Instances: 1 +After longjmp(): Instances: 1 +
    -

    This compliant solution replaces the calls to setjmp() and longjmp() with a throw expression and a catch statement.

    - #include <iostream> +

    + This compliant solution replaces the calls to + + setjmp() + + and + + longjmp() + + with a + + throw + + expression and a + + catch + + statement. +

    + + #include <iostream> struct Counter { static int instances; @@ -73,16 +209,33 @@ int main() { } std::cout << "After catch: Instances: " << Counter::instances << std::endl; } - -

    This solution produces the following output.

    - Before throw: Instances: 0 + +

    + This solution produces the following output. +

    + + Before throw: Instances: 0 f(): Instances: 1 From catch: Instances: 0 After catch: Instances: 0 - +
    -

    Using setjmp() and longjmp() could lead to a denial-of-service attack due to resources not being properly destroyed.

    +

    + Using + + setjmp() + + and + + longjmp() + + could lead to a + + denial-of-service attack + + due to resources not being properly destroyed. +

    @@ -119,10 +272,14 @@ After catch: Instances: 0 Medium @@ -155,7 +312,9 @@ After catch: Instances: 0 20.10 @@ -186,11 +347,15 @@ After catch: Instances: 0 3.9 @@ -201,10 +366,13 @@ After catch: Instances: 0 @@ -236,7 +406,11 @@ After catch: Instances: 0 2021.4 @@ -250,7 +424,9 @@ After catch: Instances: 0 @@ -317,7 +499,9 @@ After catch: Instances: 0 20.10 @@ -342,7 +530,17 @@ After catch: Instances: 0
    - P4 + + P4 + - L3 + + L3 +
    - include-setjmp + + include-setjmp + Fully checked @@ -171,7 +330,9 @@ After catch: Instances: 0 7.2.0 - CertC++-ERR52 + + CertC++-ERR52 + - cert-err52-cpp + + cert-err52-cpp + Checked by - clang-tidy + + clang-tidy + .
    - 6.2p0 + 6.1p0 - BADFUNC.LONGJMPBADFUNC.SETJMP + + BADFUNC.LONGJMP + BADFUNC.SETJMP + Use of longjmp @@ -221,7 +389,9 @@ After catch: Instances: 0 2021.2 - C++5015 + + C++5015 + - MISRA.STDLIB.LONGJMP + + + MISRA.STDLIB.LONGJMP + + - 43 S + + 43 S + Fully implemented @@ -266,8 +442,12 @@ After catch: Instances: 0 2021.2 - CERT_CPP-ERR52-a - CERT_CPP-ERR52-b + + CERT_CPP-ERR52-a + + + CERT_CPP-ERR52-b + The setjmp macro and the longjmp function shall not be used @@ -302,7 +482,9 @@ After catch: Instances: 0 4.4 - 5015 + + 5015 + - include-setjmp + + include-setjmp + Fully checked @@ -333,7 +517,11 @@ After catch: Instances: 0 4.10 - S982 + + + S982 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -357,9 +555,13 @@ After catch: Instances: 0 diff --git a/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock-standard.qhelp b/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock-standard.qhelp index 4a21b9a762..fba43e59a7 100644 --- a/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock-standard.qhelp +++ b/cpp/cert/src/rules/ERR53-CPP/DestroyedValueReferencedInConstructorDestructorCatchBlock-standard.qhelp @@ -1,19 +1,70 @@
    -

    When an exception is caught by a function-try-block handler in a constructor, any fully constructed base classes and class members of the object are destroyed prior to entering the handler [ISO/IEC 14882-2014]. Similarly, when an exception is caught by a function-try-block handler in a destructor, all base classes and nonvariant class members of the objects are destroyed prior to entering the handler. Because of this behavior, the C++ Standard, [except.handle], paragraph 10, states the following:

    +

    + When an exception is caught by a + + + function-try-block + + + handler in a constructor, any fully constructed base classes and class members of the object are destroyed prior to entering the handler [ + + ISO/IEC 14882-2014 + + ]. Similarly, when an exception is caught by a + + function-try-block + + handler in a destructor, all base classes and nonvariant class members of the objects are destroyed prior to entering the handler. Because of this behavior, the C++ Standard,ย [except.handle], paragraph 10, states the following: +

    -

    Referring to any non-static member or base class of an object in the handler for a function-try-block of a constructor or destructor for that object results in undefined behavior.

    +

    + Referring to any non-static member or base class of an object in the handler for a + + function-try-block + + of aย constructor or destructor for that object results in undefined behavior. +

    -

    Do not reference base classes or class data members in a constructor or destructor function-try-block handler. Doing so results in undefined behavior.

    +

    + Do not reference base classes or class data members in a constructor or destructor + + function-try-block + + handler. Doing so results in + + undefined behavior + + . +

    -

    In this noncompliant code example, the constructor for class C handles exceptions with a function-try-block. However, it generates undefined behavior by inspecting its member field str.

    - #include <string> - +

    + In this noncompliant code example, the constructor for class + + C + + handles exceptions with a + + function-try-block + + . However, it generates + + undefined behavior + + by inspecting its member field + + str + + . +

    + + #include <string> +ย  class C { std::string str; - +ย  public: C(const std::string &s) try : str(s) { // ... @@ -23,11 +74,18 @@ public: } } }; - +
    -

    In this compliant solution, the handler inspects the constructor parameter rather than the class data member, thereby avoiding undefined behavior.

    - #include <string> +

    + In this compliant solution, the handler inspects the constructor parameter rather than the class data member, thereby avoiding + + undefined behavior + + . +

    + + #include <string> class C { std::string str; @@ -40,10 +98,17 @@ public: // ... } } -}; +}; +
    -

    Accessing nonstatic data in a constructor's exception handler or a destructor's exception handler leads to undefined behavior.

    +

    + Accessing nonstatic data in a constructor's exception handler or a destructor's exception handler leads to + + undefined behavior + + . +

    Rule 13.3, Do not use - setjmp() + + setjmp() + and - longjmp() + + longjmp() +
    @@ -80,10 +145,14 @@ public: Medium @@ -116,7 +185,9 @@ public: 20.10 @@ -147,7 +220,9 @@ public: 3.9 @@ -162,7 +237,9 @@ public: 2021.2 @@ -177,7 +254,11 @@ public: 2021.4 @@ -191,7 +272,9 @@ public: @@ -257,7 +345,9 @@ public: 20.10
    - P2 + + P2 + - L3 + + L3 +
    - exception-handler-member-access + + exception-handler-member-access + Fully checked @@ -132,7 +203,9 @@ public: 7.2.0 - CertC++-ERR53 + + CertC++-ERR53 + - -Wexceptions + + -Wexceptions + - C++3510 + + C++3510 + - MISRA.CTOR.TRY.NON_STATIC + + + MISRA.CTOR.TRY.NON_STATIC + + - 549 S + + 549 S + Partially implemented @@ -207,7 +290,9 @@ public: 2021.2 - CERT_CPP-ERR53-a + + CERT_CPP-ERR53-a + Handlers of a function-try-block implementation of a class constructor or destructor shall not reference nonstatic members from this class or its bases @@ -241,8 +326,11 @@ public: 4.4 - 3510 - + + 3510 + + + - exception-handler-member-access + + exception-handler-member-access + Fully checked @@ -267,7 +357,17 @@ public:
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert-standard.qhelp b/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert-standard.qhelp index e6e684ac81..28703c0aa3 100644 --- a/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert-standard.qhelp +++ b/cpp/cert/src/rules/ERR54-CPP/CatchBlockShadowingCert-standard.qhelp @@ -1,15 +1,44 @@
    -

    The C++ Standard, [except.handle], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [except.handle], paragraph 4 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The handlers for a try block are tried in order of appearance. That makes it possible to write handlers that can never be executed, for example by placing a handler for a derived class after a handler for a corresponding base class.

    +

    + The handlers for a try block are tried in order of appearance. That makes it possible to write handlers thatย can never be executed, for example by placing a handler for a derived class after a handler for a correspondingย base class. +

    -

    Consequently, if two handlers catch exceptions that are derived from the same base class (such as std::exception), the most derived exception must come first.

    +

    + Consequently, if two handlers catch exceptions that are derived from the same base class (such as + + std::exception + + ), the most derived exception must come first. +

    -

    In this noncompliant code example, the first handler catches all exceptions of class B, as well as exceptions of class D, since they are also of class B. Consequently, the second handler does not catch any exceptions.

    - // Classes used for exception handling +

    + In this noncompliant code example, the first handler catches all exceptions of class + + B + + , as well as exceptions of class + + D + + , since they are also of class + + B + + . Consequently, the second handler does not catch any exceptions. +

    + + // Classes used for exception handling class B {}; class D : public B {}; @@ -21,11 +50,23 @@ void f() { } catch (D &d) { // ... } -} +} +
    -

    In this compliant solution, the first handler catches all exceptions of class D, and the second handler catches all the other exceptions of class B.

    - // Classes used for exception handling +

    + In this compliant solution, the first handler catches all exceptions of class + + D + + , and the second handler catches all the other exceptions of class + + B + + . +

    + + // Classes used for exception handling class B {}; class D : public B {}; @@ -37,10 +78,13 @@ void f() { } catch (B &b) { // ... } -} +} +
    -

    Exception handlers with inverted priorities cause unexpected control flow when an exception of the derived type occurs.

    +

    + Exception handlers with inverted priorities cause unexpected control flow when an exception of the derived type occurs. +

    @@ -77,10 +121,14 @@ void f() { Low @@ -113,7 +161,9 @@ void f() { 20.10 @@ -144,27 +196,13 @@ void f() { 3.9 - - - - - - @@ -206,9 +248,18 @@ void f() { 2021.4 @@ -222,7 +273,9 @@ void f() { @@ -274,7 +329,9 @@ void f() { 4.4 @@ -286,10 +343,14 @@ void f() { @@ -304,7 +365,9 @@ void f() { 20.10 @@ -329,7 +396,17 @@ void f() {
    - P18 + + P18 + - L1 + + L1 +
    - exception-caught-by-earlier-handler + + exception-caught-by-earlier-handler + Fully checked @@ -129,7 +179,9 @@ void f() { 7.2.0 - CertC++-ERR54 + + CertC++-ERR54 + - -Wexceptions + + -Wexceptions +
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.UCTCH - - Unreachable Catch -
    @@ -175,7 +213,9 @@ void f() { 1.2 - CP1.ERR36 + + CP1.ERR36 + Fully implemented @@ -191,7 +231,9 @@ void f() { 2021.2 - C++4030, C++4639 + + C++4030, C++4639 + - MISRA.CATCH.NOALL - MISRA.CATCH.WRONGORD - + + + MISRA.CATCH.NOALL + + + + + MISRA.CATCH.WRONGORD + + + + - 541 S, 556 S + + 541 S, 556 S + Fully implemented @@ -238,7 +291,9 @@ void f() { 2021.2 - CERT_CPP-ERR54-a + + CERT_CPP-ERR54-a + Where multiple handlers are provided in a single try-catch statement or function-try-block for a derived class and some or all of its bases, the handlers shall be ordered most-derived to base class @@ -260,7 +315,7 @@ void f() { Checks for: - Exception handlers not ordered from most-derived to base classxception handlers not ordered from most-derived to base class, incorrect order of ellipsis handlerncorrect order of ellipsis handler. + Exception handlers not ordered from most-derived to base class, incorrect order of ellipsis handler. Rule fully covered.
    - 4030, 4639 + + 4030, 4639 + - 7.17 + 7.16 - V759 + + + V759 + + - exception-caught-by-earlier-handler + + exception-caught-by-earlier-handler + Fully checked @@ -320,7 +383,11 @@ void f() { 4.10 - S1045 + + + S1045 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications-standard.qhelp b/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications-standard.qhelp index 0fe94fd62a..c3d9339993 100644 --- a/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications-standard.qhelp +++ b/cpp/cert/src/rules/ERR55-CPP/HonorExceptionSpecifications-standard.qhelp @@ -1,38 +1,183 @@
    -

    The C++ Standard, [except.spec], paragraph 8 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [except.spec], paragraph 8 + [ + + ISO/IEC 14882-2014 + + ], states the following + : +

    -

    A function is said to allow an exception of type E if the constant-expression in its noexcept-specification evaluates to false or its dynamic-exception-specification contains a type T for which a handler of type T would be a match (15.3) for an exception of type E.

    +

    + A function is said to + + allow + + an exception of type + + E + + if the + + constant-expression + + in its + + noexcept-specification + + evaluates to + + false + + or its + + dynamic-exception-specification + + contains a type + + T + + for which a handler of type + + T + + would be a match (15.3) for an exception of type + + E + + . +

    -

    If a function throws an exception other than one allowed by its exception-specification, it can lead to an implementation-defined termination of the program ([except.spec], paragraph 9).

    -

    If a function declared with a dynamic-exception-specification throws an exception of a type that would not match the exception-specification, the function std::unexpected() is called. The behavior of this function can be overridden but, by default, causes an exception of std::bad_exception to be thrown. Unless std::bad_exception is listed in the exception-specification, the function std::terminate() will be called.

    -

    Similarly, if a function declared with a noexcept-specification throws an exception of a type that would cause the noexcept-specification to evaluate to false, the function std::terminate() will be called.

    -

    Calling std::terminate() leads to implementation-defined termination of the program. To prevent abnormal termination of the program, any function that declares an exception-specification should restrict itself, as well as any functions it calls, to throwing only allowed exceptions.

    +

    + If a function throws an exception other than one allowed by its + + exception-specification + + , it can lead to an + + implementation-defined + + termination of the program ([except.spec], paragraph 9). +

    +

    + If a function declared with a + + dynamic-exception-specification + + throws an exception of a type that would not match the + + exception-specification + + , the function + + std::unexpected() + + is called. The behavior of this function can be overridden but, by default, causes an exception of + + std::bad_exception + + to be thrown. Unless + + std::bad_exception + + is listed in the + + exception-specification + + , the function + + std::terminate() + + will be called. +

    +

    + Similarly, if a function declared with a + + noexcept-specification + + throws an exception of a type that would cause the + + noexcept-specification + + to evaluate to + + false + + , the function + + std::terminate() + + will be called. +

    +

    + Calling + + std::terminate() + + leads to implementation-defined termination of the program.ย To prevent + + abnormal termination + + of the program, any function that declares an + + exception-specification + + should restrict itself, as well as any functions it calls, to throwing only allowed exceptions. +

    -

    In this noncompliant code example, a function is declared as nonthrowing, but it is possible for std::vector::resize() to throw an exception when the requested memory cannot be allocated.

    - #include <cstddef> +

    + In this noncompliant code example, a function is declared as nonthrowing, but it is possible for + + std::vector::resize() + + to throw an exception when the requested memory cannot be allocated. +

    + + #include <cstddef> #include <vector> - +ย  void f(std::vector<int> &v, size_t s) noexcept(true) { v.resize(s); // May throw } - +
    -

    In this compliant solution, the function's noexcept-specification is removed, signifying that the function allows all exceptions.

    - #include <cstddef> +

    + In this compliant solution, the function's + + noexcept-specification + + is removed, signifying that the function allows all exceptions. +

    + + #include <cstddef> #include <vector> void f(std::vector<int> &v, size_t s) { v.resize(s); // May throw, but that is okay -} +} +
    -

    In this noncompliant code example, the second function claims to throw only Exception1, but it may also throw Exception2.

    - #include <exception> - +

    + In this noncompliant code example, the second function claims to throw only + + Exception1 + + , but it may also throw + + + Exception2. + + +

    + + #include <exception> +ย  class Exception1 : public std::exception {}; class Exception2 : public std::exception {}; @@ -43,11 +188,17 @@ void foo() { void bar() throw (Exception1) { foo(); // Bad because foo() can throw Exception2 } - +
    -

    This compliant solution catches the exceptions thrown by foo().

    - #include <exception> +

    + This compliant solution catches the exceptions thrown by + + foo(). + +

    + + #include <exception> class Exception1 : public std::exception {}; class Exception2 : public std::exception {}; @@ -63,11 +214,22 @@ void bar() throw (Exception1) { // Handle error without rethrowing it } } - +
    -

    This compliant solution declares a dynamic exception-specification for bar(), which covers all of the exceptions that can be thrown from it.

    - #include <exception> +

    + This compliant solution declares a dynamic + + exception-specification + + for + + bar() + + , which covers all of the exceptions that can be thrown from it. +

    + + #include <exception> class Exception1 : public std::exception {}; class Exception2 : public std::exception {}; @@ -78,13 +240,42 @@ void foo() { void bar() throw (Exception1, Exception2) { foo(); -} +} +
    -

    Some vendors provide language extensions for specifying whether or not a function throws. For instance, Microsoft Visual Studio provides __declspec(nothrow)), and Clang supports __attribute__((nothrow)). Currently, the vendors do not document the behavior of specifying a nonthrowing function using these extensions. Throwing from a function declared with one of these language extensions is presumed to be undefined behavior.

    +

    + Some vendors provide language extensions for specifying whether or not a function throws. For instance, + + Microsoft Visual Studio + + provides + + __declspec(nothrow)) + + , and + + Clang + + supports + + __attribute__((nothrow)) + + . Currently, the vendors do not document the behavior of specifying a nonthrowing function using these extensions. Throwing from a function declared with one of these language extensions is presumed to be + + undefined behavior + + . +

    -

    Throwing unexpected exceptions disrupts control flow and can cause premature termination and denial of service.

    +

    + Throwing unexpected exceptions disrupts control flow and can cause premature termination and + + denial of service + + . +

    @@ -121,10 +312,14 @@ void bar() throw (Exception1, Exception2) { Low @@ -157,7 +352,9 @@ void bar() throw (Exception1, Exception2) { 20.10 @@ -188,7 +387,9 @@ void bar() throw (Exception1, Exception2) { 2021.2 @@ -202,7 +403,9 @@ void bar() throw (Exception1, Exception2) { @@ -252,7 +457,9 @@ void bar() throw (Exception1, Exception2) { 4.4 @@ -267,7 +474,9 @@ void bar() throw (Exception1, Exception2) { 20.10
    - P9 + + P9 + - L2 + + L2 +
    - unhandled-throw-noexcept + + unhandled-throw-noexcept + Partially checked @@ -173,7 +370,9 @@ void bar() throw (Exception1, Exception2) { 7.2.0 - CertC++-ERR55 + + CertC++-ERR55 + - C++4035, C++4036, C++4632 + + C++4035, C++4036, C++4632 + - 56 D + + 56 D + Partially implemented @@ -218,7 +421,9 @@ void bar() throw (Exception1, Exception2) { 2021.2 - CERT_CPP-ERR55-a + + CERT_CPP-ERR55-a + Where a function's declaration includes an exception-specification, the function shall only be capable of throwing exceptions of the indicated type(s) @@ -239,7 +444,7 @@ void bar() throw (Exception1, Exception2) { - Checks for noexcept functions exiting with exception (rule fully covered) + Checks forย noexcept functions exiting with exception (rule fully covered)
    - 4035, 4036, 4632 + + 4035, 4036, 4632 + - unhandled-throw-noexcept + + unhandled-throw-noexcept + Partially checked @@ -277,7 +486,17 @@ void bar() throw (Exception1, Exception2) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -334,7 +553,9 @@ void bar() throw (Exception1, Exception2) { diff --git a/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety-standard.qhelp b/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety-standard.qhelp index 0ab2c3f32b..3aae16836e 100644 --- a/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety-standard.qhelp +++ b/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety-standard.qhelp @@ -1,9 +1,35 @@
    -

    Proper handling of errors and exceptional situations is essential for the continued correct operation of software. The preferred mechanism for reporting errors in a C++ program is exceptions rather than error codes. A number of core language facilities, including dynamic_cast, operator new(), and typeid, report failures by throwing exceptions. In addition, the C++ standard library makes heavy use of exceptions to report several different kinds of failures. Few C++ programs manage to avoid using some of these facilities. Consequently, the vast majority of C++ programs must be prepared for exceptions to occur and must handle each appropriately. (See ERR51-CPP. Handle all exceptions.)

    -

    Because exceptions introduce code paths into a program, it is important to consider the effects of code taking such paths and to avoid any undesirable effects that might arise otherwise. Some such effects include failure to release an acquired resource, thereby introducing a leak, and failure to reestablish a class invariant after a partial update to an object or even a partial object update while maintaining all invariants. Code that avoids any such undesirable effects is said to be exception safe.

    -

    Based on the preceding effects, the following table distinguishes three kinds of exception safety guarantees from most to least desired.

    +

    + Proper handling of errors and exceptional situations is essential for the continued correct operation of software. The preferred mechanism for reporting errors in a C++ program is exceptions rather than error codes. A number of core language facilities, including + + dynamic_cast + + , + + operator new() + + , and + + typeid + + , report failures by throwing exceptions. In addition, the C++ standard library makes heavy use of exceptions to report several different kinds of failures. Few C++ programs manage to avoid using some of these facilities. Consequently, the vast majority of C++ programs must be prepared for exceptions to occur and must handle each appropriately. (See + + ERR51-CPP. Handle all exceptions + + .) +

    +

    + Because exceptions introduce code paths into a program, it is important to consider the effects of code taking such paths and to avoid any undesirable effects that might arise otherwise. Some such effects include failure to release an acquired resource, thereby introducing a leak, and failure to reestablish a class invariant after a partial update to an object or even a partial object update while maintaining all invariants. Code that avoids any such undesirable effects is said to be + + exception safe + + . +

    +

    + Based on the preceding effects, the following table distinguishes three kinds of exception safety guarantees from most to least desired. +

    " - nothrow + + nothrow + (C++)"
    @@ -19,20 +45,28 @@
    - Strong + + + Strong + + The strong exception safety guarantee is a property of an operation such that, in addition to satisfying the basic exception safety guarantee, if the operation terminates by raising an exception, it has no observable effects on program state. - + Strong Exception Safety
    - Basic + + + Basic + + The basic exception safety guarantee is a property of an operation such that, if the operation terminates by raising an exception, it preserves program state invariants and prevents resource leaks. @@ -43,26 +77,69 @@
    - None + + + None + + Code that provides neither the strong nor basic exception safety guarantee is not exception safe. - + No Exception Safety
    -

    Code that guarantees strong exception safety also guarantees basic exception safety.

    -

    Because all exceptions thrown in an application must be handled, in compliance with ERR50-CPP. Do not abruptly terminate the program, it is critical that thrown exceptions do not leave the program in an indeterminate state where invariants are violated. That is, the program must provide basic exception safety for all invariants and may choose to provide strong exception safety for some invariants. Whether exception handling is used to control the termination of the program or to recover from an exceptional situation, a violated invariant leaves the program in a state where graceful continued execution is likely to introduce security vulnerabilities. Thus, code that provides no exception safety guarantee is unsafe and must be considered defective.

    +

    + Code that guarantees strong exception safety also guarantees basic exception safety. +

    +

    + Because all exceptions thrown in an application must be handled, in compliance with + + ERR50-CPP. Do not abruptly terminate the program + + , it is critical that thrown exceptions do not leave the program in an indeterminate state where invariants are violated. That is, the program must provide basic exception safety for all invariants and may choose to provide strong exception safety for some invariants. Whether exception handling is used to control the termination of the program or to recover from an exceptional situation, a violated invariant leaves the program in a state where graceful continued execution is likely to introduce security vulnerabilities. Thus, code that provides no exception safety guarantee is unsafe and must be considered defective. +

    -

    The following noncompliant code example shows a flawed copy assignment operator. The implicit invariants of the class are that the array member is a valid (possibly null) pointer and that the nElems member stores the number of elements in the array pointed to by array. The function deallocates array and assigns the element counter, nElems, before allocating a new block of memory for the copy. As a result, if the new expression throws an exception, the function will have modified the state of both member variables in a way that violates the implicit invariants of the class. Consequently, such an object is in an indeterminate state and any operation on it, including its destruction, results in undefined behavior.

    - #include <cstring> - +

    + The following noncompliant code example shows a flawed copy assignment operator. The implicit invariants of the class are that the + + array + + member is a valid (possibly null) pointer and that the + + nElems + + member stores the number of elements in the array pointed to by + + array + + . The function deallocates + + array + + and assigns the element counter, + + nElems + + , before allocating a new block of memory for the copy. As a result, if the + + new + + expression throws an exception, the function will have modified the state of both member variables in a way that violates the implicit invariants of the class. Consequently, such an object is in an indeterminate state and any operation on it, including its destruction, results in + + undefined behavior + + . +

    + + #include <cstring> +ย  class IntArray { int *array; std::size_t nElems; @@ -73,7 +150,7 @@ public: delete[] array; } - +ย  IntArray(const IntArray& that); // nontrivial copy constructor IntArray& operator=(const IntArray &rhs) { if (this != &rhs) { @@ -90,12 +167,23 @@ public: // ... }; - +
    -

    In this compliant solution, the copy assignment operator provides the strong exception safety guarantee. The function allocates new storage for the copy before changing the state of the object. Only after the allocation succeeds does the function proceed to change the state of the object. In addition, by copying the array to the newly allocated storage before deallocating the existing array, the function avoids the test for self-assignment, which improves the performance of the code in the common case [Sutter 2004].

    - #include <cstring> - +

    + In this compliant solution, the copy assignment operator provides the + + strong exception safety + + guarantee. The function allocates new storage for the copy before changing the state of the object. Only after the allocation succeeds does the function proceed to change the state of the object. In addition, by copying the array to the newly allocated storage before deallocating the existing array, the function avoids the test for self-assignment, which improves the performance of the code in the common case [ + + Sutter 2004 + + ]. +

    + + #include <cstring> +ย  class IntArray { int *array; std::size_t nElems; @@ -122,10 +210,12 @@ public: // ... }; - +
    -

    Code that is not exception safe typically leads to resource leaks, causes the program to be left in an inconsistent or unexpected state, and ultimately results in undefined behavior at some point after the first exception is thrown.

    +

    + Code that is not exception safe typically leads to resource leaks, causes the program to be left in an inconsistent or unexpected state, and ultimately results inย undefined behavior at some point after the first exception is thrown. +

    @@ -162,10 +252,14 @@ public: High @@ -188,22 +282,6 @@ public: Description - - - - - - @@ -228,7 +308,9 @@ public: @@ -274,10 +362,22 @@ public: @@ -286,7 +386,13 @@ public:
    - P9 + + P9 + - L2 + + L2 +
    - - CodeSonar - - - 6.2p0 - - ALLOC.LEAK - - Leak -
    @@ -214,7 +292,9 @@ public: 2021.2 - C++4075, C++4076 + + C++4075, C++4076 + - 527 S, 56 D, 71 D + + 527 S, 56 D, 71 D + Partially implemented @@ -244,7 +326,10 @@ public: 2021.2 - CERT_CPP-ERR56-aCERT_CPP-ERR56-b + + CERT_CPP-ERR56-a + CERT_CPP-ERR56-b + Always catch exceptions @@ -261,8 +346,11 @@ public: 4.4 - 4075, 4076 - + + 4075, 4076 + + + - 7.17 + 7.16 - V565, V1023, V5002 + + + V565 + + , + + V1023 + + , + + V5002 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for vulnerabilities resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql b/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql index 530873afc5..b027d02e3f 100644 --- a/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql +++ b/cpp/cert/src/rules/ERR56-CPP/GuaranteeExceptionSafety.ql @@ -15,7 +15,5 @@ import codingstandards.cpp.cert import codingstandards.cpp.rules.exceptionsafetyguarantees.ExceptionSafetyGuarantees class GuaranteeExceptionSafetyQuery extends ExceptionSafetyGuaranteesSharedQuery { - GuaranteeExceptionSafetyQuery() { - this = ExceptionSafetyPackage::guaranteeExceptionSafetyQuery() - } + GuaranteeExceptionSafetyQuery() { this = ExceptionSafetyPackage::guaranteeExceptionSafetyQuery() } } diff --git a/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions-standard.qhelp b/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions-standard.qhelp index 2eaa2150a8..db75741272 100644 --- a/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions-standard.qhelp +++ b/cpp/cert/src/rules/ERR57-CPP/DoNotLeakResourcesWhenHandlingExceptions-standard.qhelp @@ -1,32 +1,81 @@
    -

    Reclaiming resources when exceptions are thrown is important. An exception being thrown may result in cleanup code being bypassed or an object being left in a partially initialized state. Such a partially initialized object would violate basic exception safety, as described in ERR56-CPP. Guarantee exception safety. It is preferable that resources be reclaimed automatically, using the RAII design pattern [Stroustrup 2001], when objects go out of scope. This technique avoids the need to write complex cleanup code when allocating resources.

    -

    However, constructors do not offer the same protection. Because a constructor is involved in allocating resources, it does not automatically free any resources it allocates if it terminates prematurely. The C++ Standard, [except.ctor], paragraph 2 [ISO/IEC 14882-2014], states the following:

    +

    + Reclaiming resources when exceptions are thrown is important. An exception being thrown may result in cleanup code being bypassed or an object being left in a partially initialized state. Such a partially initialized object would violate basic exception safety, as described in + + ERR56-CPP. Guarantee exception safety + + .ย It is preferable that resources be reclaimed automatically, using the + + RAII + + design pattern [ + + Stroustrup 2001 + + ], when objects go out of scope. This technique avoids the need to write complex cleanup code when allocating resources. +

    +

    + However, constructors do not offer the same protection. Because a constructor is involved in allocating resources, it does not automatically free any resources it allocates if it terminates prematurely. The C++ Standard,ย [except.ctor],ย paragraph 2 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects (excluding the variant members of a union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed execution and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the objectโ€™s destructor will be invoked. If the object was allocated in a new-expression, the matching deallocation function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object.

    +

    + An object of any storage duration whose initialization or destruction is terminated by an exception willย have destructors executed for all of its fully constructed subobjects (excluding the variant members of aย union-like class), that is, for subobjects for which the principal constructor (12.6.2) has completed executionย and the destructor has not yet begun execution. Similarly, if the non-delegating constructor for an objectย has completed execution and a delegating constructor for that object exits with an exception, the objectโ€™sย destructor will be invoked. If the object was allocated in a new-expression, the matching deallocationย function (3.7.4.2, 5.3.4, 12.5), if any, is called to free the storage occupied by the object. +

    -

    It is generally recommended that constructors that cannot complete their job should throw exceptions rather than exit normally and leave their object in an incomplete state [Cline 2009].

    -

    Resources must not be leaked as a result of throwing an exception, including during the construction of an object.

    -

    This rule is a subset of MEM51-CPP. Properly deallocate dynamically allocated resources, as all failures to deallocate resources violate that rule.

    +

    + It is generally recommended that constructors that cannot complete their job should throw exceptions rather than exit normally and leave their object in an incomplete stateย [ + + Cline 2009 + + ]. +

    +

    + Resources must not be leaked as a result of throwing an exception, including during the construction of an object. +

    +

    + + This rule is a subset of + + MEM51-CPP. Properly deallocate dynamically allocated resources + + , as all failures to deallocate resources violate that rule. + +

    -

    In this noncompliant code example, pst is not properly released when process_item throws an exception, causing a resource leak.

    - #include <new> - +

    + In this noncompliant code example, + + pst + + is not properly released when + + process_item + + throws an exception, causing a resource leak. +

    + + #include <new> +ย  struct SomeType { SomeType() noexcept; // Performs nontrivial initialization. ~SomeType(); // Performs nontrivial finalization. void process_item() noexcept(false); }; - +ย  void f() { SomeType *pst = new (std::nothrow) SomeType(); if (!pst) { // Handle error return; } - +ย  try { pst->process_item(); } catch (...) { @@ -35,11 +84,21 @@ void f() { } delete pst; } - +
    -

    In this compliant solution, the exception handler frees pst by calling delete.

    - #include <new> +

    + In this compliant solution, the exception handler frees + + pst + + by calling + + delete. + +

    + + #include <new> struct SomeType { SomeType() noexcept; // Performs nontrivial initialization. @@ -62,16 +121,42 @@ void f() { throw; } delete pst; -} -

    While this compliant solution properly releases its resources using catch clauses, this approach can have some disadvantages:

    +} +
    +

    + While this compliant solution properly releases its resources using + + catch + + clauses, this approachย can have some disadvantages: +

      -
    • Each distinct cleanup requires its own try and catch blocks.
    • -
    • The cleanup operation must not throw any exceptions.
    • +
    • + Each distinct cleanup requires its own + + try + + and + + catch + + blocks. +
    • +
    • + The cleanup operation must not throw any exceptions. +
    -

    A better approach is to employ RAII. This pattern forces every object to clean up after itself in the face of abnormal behavior, preventing the programmer from having to do so. Another benefit of this approach is that it does not require statements to handle resource allocation errors, in conformance with MEM52-CPP. Detect and handle memory allocation errors.

    - struct SomeType { +

    + A better approach is to employ RAII. This pattern forces every object to clean up after itself in the face of abnormal behavior, preventing the programmer from having to do so. Another benefit of this approach is that it does not require statements to handle resource allocation errors, in conformance with + + MEM52-CPP. Detect and handle memory allocation errors + + . +

    + + struct SomeType { SomeType() noexcept; // Performs nontrivial initialization. ~SomeType(); // Performs nontrivial finalization. @@ -87,11 +172,50 @@ void f() { throw; } // After re-throwing the exception, the destructor is run for st. } // If f() exits without throwing an exception, the destructor is run for st. - +
    -

    In this noncompliant code example, the C::C() constructor might fail to allocate memory for a, might fail to allocate memory for b, or might throw an exception in the init() method. If init() throws an exception, neither a nor b will be released. Likewise, if the allocation for b fails, a will not be released.

    - struct A {/* ... */}; +

    + In this noncompliant code example, the + + C::C() + + constructor might fail to allocate memory for + + a + + , might fail to allocate memory for + + b + + , or might throw an exception in the + + init() + + method. If + + init() + + throws an exception, neither + + a + + nor + + b + + will be released. Likewise, if the allocation for + + b + + fails, + + a + + will not be released. +

    + + struct A {/* ... */}; struct B {/* ... */}; class C { @@ -104,13 +228,28 @@ public: init(); } }; - +
    -

    This compliant solution mitigates the potential failures by releasing a and b if an exception is thrown during their allocation or during init().

    - struct A {/* ... */}; +

    + This compliant solution mitigates the potential failures by releasing + + a + + and + + b + + if an exception is thrown during their allocation or during + + init() + + . +

    + + struct A {/* ... */}; struct B {/* ... */}; - +ย  class C { A *a; B *b; @@ -129,12 +268,27 @@ public: } } }; - +
    -

    This compliant solution uses std::unique_ptr to create objects that clean up after themselves should anything go wrong in the C::C() constructor. The std::unique_ptr applies the principles of RAII to pointers.

    - #include <memory> - +

    + This compliant solution uses + + std::unique_ptr + + to create objects that clean up after themselves should anything go wrong in the + + C::C() + + constructor. The + + std::unique_ptr + + applies the principles of RAII to pointers. +

    + + #include <memory> +ย  struct A {/* ... */}; struct B {/* ... */}; @@ -147,10 +301,17 @@ public: C() : a(new A()), b(new B()) { init(); } -}; +}; +
    -

    Memory and other resource leaks will eventually cause a program to crash. If an attacker can provoke repeated resource leaks by forcing an exception to be thrown through the submission of suitably crafted data, then the attacker can mount a denial-of-service attack.

    +

    + Memory and other resource leaks will eventually cause a program to crash. If an attacker can provoke repeated resource leaks by forcing an exception to be thrown through the submission of suitably crafted data, then the attacker can mount a + + denial-of-service attack + + . +

    @@ -187,10 +348,14 @@ public: High @@ -220,10 +385,12 @@ public: @@ -254,12 +423,24 @@ public: 2021.4 @@ -273,7 +454,9 @@ public:
    - P2 + + P2 + - L3 + + L3 +
    - 6.2p0 + 6.1p0 - ALLOC.LEAK + + ALLOC.LEAK + Leak @@ -239,7 +406,9 @@ public: 2021.2 - C++4756, C++4757, C++4758 + + C++4756, C++4757, C++4758 + - CL.MLK - MLK.MIGHT - MLK.MUST - MLK.RET.MIGHT - MLK.RET.MUST - RH.LEAK + + CL.MLK + + + MLK.MIGHT + + + MLK.MUST + + + MLK.RET.MIGHT + + + MLK.RET.MUST + + + RH.LEAK + - 50 D + + 50 D + Partially implemented @@ -289,7 +472,9 @@ public: 2021.2 - CERT_CPP-ERR57-a + + CERT_CPP-ERR57-a + Ensure resources are freed @@ -311,14 +496,24 @@ public: Checks for: - Resource leak caused by exceptionesource leak caused by exception, object left in partially initialized statebject left in partially initialized state, bad allocation in constructorad allocation in constructor. + Resource leak caused by exception, object left in partially initialized state, bad allocation in constructor.
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting-standard.qhelp b/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting-standard.qhelp index 3a5bc8e0ae..df7d10c74d 100644 --- a/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting-standard.qhelp +++ b/cpp/cert/src/rules/ERR58-CPP/HandleAllExceptionsThrownBeforeMainBeginsExecuting-standard.qhelp @@ -1,27 +1,108 @@
    -

    Not all exceptions can be caught, even with careful use of function-try-blocks. The C++ Standard, [except.handle], paragraph 13 [ISO/IEC 14882-2014], states the following:

    +

    + Not all exceptions can be caught, even with careful use of + + function-try-blocks + + . The C++ Standard,ย [except.handle], paragraph 13 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    Exceptions thrown in destructors of objects with static storage duration or in constructors of namespace scope objects with static storage duration are not caught by a function-try-block on main() . Exceptions thrown in destructors of objects with thread storage duration or in constructors of namespace-scope objects with thread storage duration are not caught by a function-try-block on the initial function of the thread.

    +

    + Exceptions thrown in destructors of objects with static storage duration or in constructors of namespace scope objects with static storage duration are not caught by a + + function-try-block + + on + + main() + + . Exceptionsย thrown in destructors of objects with thread storage duration or in constructors of namespace-scope objectsย with thread storage duration are not caught by a function-try-block on the initial function of the thread. +

    -

    When declaring an object with static or thread storage duration, and that object is not declared within a function block scope, the type's constructor must be declared noexcept and must comply with ERR55-CPP. Honor exception specifications. Additionally, the initializer for such a declaration, if any, must not throw an uncaught exception (including from any implicitly constructed objects that are created as a part of the initialization). If an uncaught exception is thrown before main() is executed, or if an uncaught exception is thrown after main() has finished executing, there are no further opportunities to handle the exception and it results in implementation-defined behavior. (See ERR50-CPP. Do not abruptly terminate the program for further details.)

    -

    For more information on exception specifications of destructors, see DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions.

    +

    + When declaring an object with static or thread storage duration, and that object is not declared within a function block scope, the type's constructor must be declared + + noexcept + + and must comply with + + ERR55-CPP. Honor exception specifications + + . Additionally, the initializer for such a declaration, if any, must not throw an uncaught exception (including from any implicitly constructed objects that are created as a part of the initialization). If an uncaught exception is thrown before + + main() + + is executed, or if an uncaught exception is thrown after + + main() + + has finished executing, there are no further opportunities to handle the exception and itย results in implementation-defined behavior. (See + + ERR50-CPP. Do not abruptly terminate the program + + for further details.) +

    +

    + For more information on exception specifications of destructors, see + + DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions + + . +

    -

    In this noncompliant example, the constructor for S may throw an exception that is not caught when globalS is constructed during program startup.

    - struct S { +

    + In this noncompliant example, the constructor for + S + may throw an exception that is not caught when + + globalS + + is constructed during program startup. +

    + + struct S { S() noexcept(false); }; - -static S globalS; +ย  +static S globalS; +
    -

    This compliant solution makes globalS into a local variable with static storage duration, allowing any exceptions thrown during object construction to be caught because the constructor for S will be executed the first time the function globalS() is called rather than at program startup. This solution does require the programmer to modify source code so that previous uses of globalS are replaced by a function call to globalS().

    - struct S { +

    + This compliant solution makes + + globalS + + into a local variable with static storage duration, allowing any exceptions thrown during object construction to be caught because the constructor for + + S + + will be executed the first time the function + + globalS() + + is called rather than at program startup. This solution does require the programmer to modify source code so that previous uses of + + globalS + + are replaced by a function call to + + globalS() + + . +

    + + struct S { S() noexcept(false); }; - +ย  S &globalS() { try { static S s; @@ -30,11 +111,47 @@ S &globalS() { // Handle error, perhaps by logging it and gracefully terminating the application. } // Unreachable. -} +} +
    -

    In this noncompliant example, the constructor of global may throw an exception during program startup. (The std::string constructor, which accepts a const char * and a default allocator object, is not marked noexcept and consequently allows all exceptions.) This exception is not caught by the function-try-block on main(), resulting in a call to std::terminate() and abnormal program termination.

    - #include <string> +

    + In this noncompliant example, the constructor of + + global + + may throw an exception during program startup. (The + + std::string + + constructor, whichย accepts a + + const char * + + and a default allocator object, is not marked + + noexcept + + and consequently allows all exceptions.) This exception is not caught by the + + function-try-block + + on + + main() + + , resulting in a call to + + std::terminate() + + and + + abnormal program termination + + . +

    + + #include <string> static const std::string global("..."); @@ -44,20 +161,54 @@ try { } catch(...) { // IMPORTANT: Will not catch exceptions thrown // from the constructor of global -} +} +
    -

    Compliant code must prevent exceptions from escaping during program startup and termination. This compliant solution avoids defining a std::string at global namespace scope and instead uses a static const char *.

    - static const char *global = "..."; +

    + Compliant code must prevent exceptions from escaping during program startup and termination. This compliant solution avoids defining a + + std::string + + at global namespace scope and instead uses a + + static const char * + + . +

    + + static const char *global = "..."; int main() { // ... -} +} +
    -

    This compliant solution introduces a class derived from std::string with a constructor that catches all exceptions with a function try block and terminates the application in accordance with ERR50-CPP-EX1 in ERR50-CPP. Do not abruptly terminate the program in the event any exceptions are thrown. Because no exceptions can escape the constructor, it is marked noexcept and the class type is permissible to use in the declaration or initialization of a static global variable.

    -

    For brevity, the full interface for such a type is not described.

    - #include <exception> +

    + This compliant solution introduces a class derived from + + std::string + + with a constructor that catches all exceptions with a function try block and terminates the application in accordance with + + ERR50-CPP-EX1 + + in + + ERR50-CPP. Do not abruptly terminate the program + + in the event any exceptions are thrown. Because no exceptions can escape the constructor, it is marked + + noexcept + + and the class type is permissible to use in the declaration or initialization of a static global variable. +

    +

    + For brevity, the full interface for such a type is not described. +

    + + #include <exception> #include <string> namespace my { @@ -72,26 +223,50 @@ struct string : std::string { // ... }; } - +ย  static const my::string global("..."); int main() { // ... -} +} +
    -

    In this noncompliant example, an exception may be thrown by the initializer for the static global variable i.

    - extern int f() noexcept(false); +

    + In this noncompliant example, an exception may be thrown by the initializer for the static global variable + + i + + . +

    + + extern int f() noexcept(false); int i = f(); - +ย  int main() { // ... -} +} +
    -

    This compliant solution wraps the call to f() with a helper function that catches all exceptions and terminates the program in conformance with ERR50-CPP-EX1 of ERR50-CPP. Do not abruptly terminate the program.

    - #include <exception> - +

    + This compliant solution wraps the call to + + f() + + with a helper function that catches all exceptions and terminates the program in conformance with + + ERR50-CPP-EX1 + + of + + ERR50-CPP. Do not abruptly terminate the program + + . +

    + + #include <exception> +ย  int f_helper() noexcept { try { extern int f() noexcept(false); @@ -103,15 +278,26 @@ int f_helper() noexcept { } // Unreachable. } - +ย  int i = f_helper(); int main() { // ... -} +} +
    -

    Throwing an exception that cannot be caught results in abnormal program termination and can lead to denial-of-service attacks.

    +

    + Throwing an exception that cannot be caught results in + + abnormal program termination + + and can lead to + + denial-of-service attacks + + . +

    @@ -148,10 +334,14 @@ int main() { Low @@ -184,7 +374,9 @@ int main() { 20.10 @@ -215,11 +409,15 @@ int main() { 3.9 @@ -232,7 +430,9 @@ int main() { 2021.2 @@ -247,7 +447,9 @@ int main() { 2021.2 @@ -296,7 +500,9 @@ int main() { 20.10
    - P9 + + P9 + - L2 + + L2 +
    - potentially-throwing-static-initialization + + potentially-throwing-static-initialization + Partially checked @@ -200,7 +392,9 @@ int main() { 7.2.0 - CertC++-ERR58 + + CertC++-ERR58 + - cert-err58-cpp + + cert-err58-cpp + Checked by - clang-tidy + + clang-tidy +
    - C++4634, C++4636, C++4637, C++4639 + + C++4634, C++4636, C++4637, C++4639 + - CERT_CPP-ERR58-a + + CERT_CPP-ERR58-a + Exceptions shall be raised only after start-up and before termination of the program @@ -281,7 +483,9 @@ int main() { 4.4 - 4634, 4636, 4637, 4639 + + 4634, 4636, 4637, 4639 + - potentially-throwing-static-initialization + + potentially-throwing-static-initialization + Partially checked @@ -306,10 +512,29 @@ int main() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of ERR50-CPP. Do not abruptly terminate the program

    +

    + + This rule is a subset of + + + + ERR50-CPP. Do not abruptly terminate the program + + +

    diff --git a/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries-standard.qhelp b/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries-standard.qhelp index 586abf3621..ce5d76f641 100644 --- a/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries-standard.qhelp +++ b/cpp/cert/src/rules/ERR59-CPP/DoNotThrowAnExceptionAcrossExecutionBoundaries-standard.qhelp @@ -1,15 +1,44 @@
    -

    Throwing an exception requires collaboration between the execution of the throw expression and the passing of control to the appropriate catch statement, if one applies. This collaboration takes the form of runtime logic used to calculate the correct handler for the exception and is an implementation detail specific to the platform. For code compiled by a single C++ compiler, the details of how to throw and catch exceptions can be safely ignored. However, when throwing an exception across execution boundaries, care must be taken to ensure the runtime logic used is compatible between differing sides of the execution boundary.

    -

    An execution boundary is the delimitation between code compiled by differing compilers, including different versions of a compiler produced by the same vendor. For instance, a function may be declared in a header file but defined in a library that is loaded at runtime. The execution boundary is between the call site in the executable and the function implementation in the library. Such boundaries are also called ABI (application binary interface) boundaries because they relate to the interoperability of application binaries.

    -

    Throw an exception across an execution boundary only when both sides of the execution boundary use the same ABI for exception handling.

    +

    + Throwing an exception requires collaboration between the execution of the + + throw + + expression and the passing of control to the appropriate + + catch + + statement, if one applies. This collaboration takes the form of runtime logic used to calculate the correct handler for the exception and is an implementation detail specific to the platform. For code compiled by a single C++ compiler, the details of how to throw and catch exceptions can be safely ignored. However, when throwing an exception across execution boundaries, care must be taken to ensure the runtime logic used is compatible between differing sides of the execution boundary. +

    +

    + An + + execution boundary + + is the delimitation between code compiled by differing compilers, including different versions of a compiler produced by the same vendor. For instance, a function may be declared in a header file but defined in a library that is loaded at runtime. The execution boundary is between the call site in the executable and the function implementation in the library. Such boundaries are also called + + ABI + + (application binary interface) boundaries because they relate to the interoperability of application binaries. +

    +

    + Throw an exception across an execution boundary only when both sides of the execution boundary use the same ABI for exception handling. +

    -

    In this noncompliant code example, an exception is thrown from a library function to signal an error. Despite the exception being a scalar type (and thus implicitly conforming to EXP60-CPP. Do not pass a nonstandard-layout type object across execution boundaries), this code can still result in abnormal program execution if the library and application adhere to different ABIs.

    - // library.h +

    + In this noncompliant code example, an exception is thrown from a library function to signal an error. Despite the exception being a scalar type (and thus implicitly conforming to + + EXP60-CPP. Do not pass a nonstandard-layout type object across execution boundaries + + ), this code can still result in abnormal program execution if the library and application adhere to different ABIs. +

    + + // library.h void func() noexcept(false); // Implemented by the library - +ย  // library.cpp void func() noexcept(false) { // ... @@ -17,7 +46,7 @@ void func() noexcept(false) { throw 42; } } - +ย  // application.cpp #include "library.h" @@ -27,13 +56,43 @@ void f() { } catch(int &e) { // Handle error } -} -

    Implementation Details

    -

    If the library code is compiled (with modification to account for mangling differences) with GCC 4.9 on a default installation of MinGW-w64 without special compiler flags, the exception throw will rely on the zero-cost, table-based exception model that is based on DWARF and uses the Itanium ABI. If the application code is compiled with Microsoft Visual Studio 2013, the catch handler will be based on Structured Exception Handling and the Microsoft ABI. These two exception-handling formats are incompatible, as are the ABIs, resulting in abnormal program behavior. Specifically, the exception thrown by the library is not caught by the application, and std::terminate() is eventually called.

    +} +
    +

    + + Implementation Details + +

    +

    + If the library code is compiled (with modification to account for mangling differences) with + + GCC + + 4.9 on a default installation of MinGW-w64 without special compiler flags, the exception throw will rely on the zero-cost, table-based exception model that is based on + + DWARF + + and uses the Itanium ABI. If the application code is compiled with + + Microsoft Visual Studio + + 2013, the catch handler will be based on + + Structured Exception Handling + + and the Microsoft ABI. These two exception-handling formats are incompatible, as are the ABIs, resulting in abnormal program behavior. Specifically, the exception thrown by the library is not caught by the application, and + + std::terminate() + + is eventually called. +

    -

    In this compliant solution, the error from the library function is indicated by a return value instead of an exception. Using Microsoft Visual Studio (or GCC) to compile both the library and the application would also be a compliant solution because the same exception-handling machinery and ABI would be used on both sides of the execution boundary.

    - // library.h +

    + In this compliant solution, the error from the library function is indicated by a return value instead of an exception. Using Microsoft Visual Studio (or GCC) to compile both the library and the application would also be a compliant solution because the same exception-handling machinery and ABI would be used on both sides of the execution boundary. +

    + + // library.h int func() noexcept(true); // Implemented by the library // library.cpp @@ -53,10 +112,21 @@ void f() { if (int err = func()) { // Handle error } -} +} +
    -

    The effects of throwing an exception across execution boundaries depends on the implementation details of the exception-handling mechanics. They can range from correct or benign behavior to undefined behavior.

    +

    + The effects of throwing an exception across execution boundaries depends on the + + implementation details + + of the exception-handling mechanics. They can range from correct or benign behavior to + + undefined behavior + + . +

    @@ -93,10 +163,14 @@ void f() { Medium @@ -129,7 +203,9 @@ void f() { 2021.2 @@ -144,7 +220,9 @@ void f() { 2021.2
    - P12 + + P12 + - L1 + + L1 +
    - C++3809, C++3810 + + C++3809, C++3810 + - CERT_CPP-ERR59-a + + CERT_CPP-ERR59-a + Do not throw an exception across execution boundaries @@ -154,7 +232,17 @@ void f() {
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible-standard.qhelp b/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible-standard.qhelp index 0e56232676..c52805595a 100644 --- a/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible-standard.qhelp +++ b/cpp/cert/src/rules/ERR60-CPP/ExceptionObjectsMustBeNothrowCopyConstructible-standard.qhelp @@ -1,17 +1,122 @@
    -

    When an exception is thrown, the exception object operand of the throw expression is copied into a temporary object that is used to initialize the handler. The C++ Standard, [except.throw], paragraph 3 [ISO/IEC 14882-2014], in part, states the following:

    +

    + When an exception is thrown, the exception object operand of the + + throw + + expression is copied into a temporary object that is used to initialize the handler. The C++ Standard,ย [except.throw], paragraph 3 [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    Throwing an exception copy-initializes a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler.

    +

    + Throwing an exception copy-initializes a temporary object, called the + + exception object + + . Theย temporary is an lvalue and is used to initialize the variable declared in the matching + + handler + + . +

    -

    If the copy constructor for the exception object type throws during the copy initialization, std::terminate() is called, which can result in possibly unexpected implementation-defined behavior. For more information on implicitly calling std::terminate(), see ERR50-CPP. Do not abruptly terminate the program.

    -

    The copy constructor for an object thrown as an exception must be declared noexcept, including any implicitly-defined copy constructors. Any function declared noexcept that terminates by throwing an exception violates ERR55-CPP. Honor exception specifications.

    -

    The C++ Standard allows the copy constructor to be elided when initializing the exception object to perform the initialization if a temporary is thrown. Many modern compiler implementations make use of both optimization techniques. However, the copy constructor for an exception object still must not throw an exception because compilers are not required to elide the copy constructor call in all situations, and common implementations of std::exception_ptr will call a copy constructor even if it can be elided from a throw expression.

    +

    + If the copy constructor for the exception object type throws during the copy initialization, + + std::terminate() + + is called, which can result in possibly unexpected + + implementation-defined behavior + + . For more information on implicitly calling + + std::terminate() + + , see + + ERR50-CPP. Do not abruptly terminate the program + + . +

    +

    + The copy constructor for an object thrown as an exception must be declared + + noexcept + + , including any implicitly-defined copy constructors.ย Any function declared + + noexcept + + that terminates by throwing an exception violates + + ERR55-CPP. Honor exception specifications + + . +

    +

    + The C++ Standard allows the copy constructor to be elidedย when initializing the exception object to perform the initialization if a temporary is thrown. Many modern compiler implementations make use of both optimization techniques. However, the copy constructor for an exception object still must not throw an exception because compilers are not requiredย to elide the copy constructor call in all situations, and common implementations of + + std::exception_ptr + + will call a copy constructor even if it can be elided from a + + throw + + expression. +

    -

    In this noncompliant code example, an exception of type S is thrown in f(). However, because S has a std::string data member, and the copy constructor for std::string is not declared noexcept, the implicitly-defined copy constructor for S is also not declared to be noexcept. In low-memory situations, the copy constructor for std::string may be unable to allocate sufficient memory to complete the copy operation, resulting in a std::bad_alloc exception being thrown.

    - #include <exception> +

    + In this noncompliant code example, an exception of type + + S + + is thrown in + + f() + + . However, because + + S + + has a + + std::string + + data member, and the copy constructor for + + std::string + + is not declared + + noexcept + + , the implicitly-defined copy constructor for + + S + + is also not declared to be + + noexcept + + . In low-memory situations, the copy constructor for + + std::string + + may be unable to allocate sufficient memory to complete the copy operation, resulting in a + + std::bad_alloc + + exception being thrown. +

    + + #include <exception> #include <string> class S : public std::exception { @@ -23,7 +128,7 @@ public: return m.c_str(); } }; - +ย  void g() { // If some condition doesn't hold... throw S("Condition did not hold"); @@ -35,17 +140,38 @@ void f() { } catch (S &s) { // Handle error } -} +} +
    -

    This compliant solution assumes that the type of the exception object can inherit from std::runtime_error, or that type can be used directly. Unlike std::string, a std::runtime_error object is required to correctly handle an arbitrary-length error message that is exception safe and guarantees the copy constructor will not throw [ ISO/IEC 14882-2014 ].

    - #include <stdexcept> +

    + This compliant solution assumes that the type of the exception object can inherit from + + std::runtime_error + + , or that type can be used directly. Unlike + + std::string + + , a + + std::runtime_error + + object is required to correctly handle an arbitrary-length error message that is exception safe and guarantees the copy constructor will not throw + [ + + ISO/IEC 14882-2014 + + ]. +

    + + #include <stdexcept> #include <type_traits> struct S : std::runtime_error { S(const char *msg) : std::runtime_error(msg) {} }; - +ย  static_assert(std::is_nothrow_copy_constructible<S>::value, "S must be nothrow copy constructible"); @@ -60,11 +186,19 @@ void f() { } catch (S &s) { // Handle error } -} +} +
    -

    If the exception type cannot be modified to inherit from std::runtime_error, a data member of that type is a legitimate implementation strategy, as shown in this compliant solution.

    - #include <stdexcept> +

    + If the exception type cannot be modified to inherit from + + std::runtime_error + + , a data member of that type is a legitimate implementation strategy, as shown in this compliant solution. +

    + + #include <stdexcept> #include <type_traits> class S : public std::exception { @@ -76,7 +210,7 @@ public: return m.what(); } }; - +ย  static_assert(std::is_nothrow_copy_constructible<S>::value, "S must be nothrow copy constructible"); @@ -91,10 +225,21 @@ void f() { } catch (S &s) { // Handle error } -} +} +
    -

    Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.

    +

    + Allowing the application to + + abnormally terminate + + can lead to resources not being freed, closed, and so on. It is frequently a vector for + + denial-of-service attacks + + . +

    @@ -131,10 +276,14 @@ void f() { Medium @@ -167,11 +316,15 @@ void f() { 3.9 @@ -184,7 +337,9 @@ void f() { 2021.2 @@ -199,8 +354,12 @@ void f() { 2021.2 @@ -226,7 +387,17 @@ void f() {
    - P4 + + P4 + - L3 + + L3 +
    - cert-err60-cpp + + cert-err60-cpp + Checked by - clang-tidy + + clang-tidy +
    - C++3508 + + C++3508 + - CERT_CPP-ERR60-a - CERT_CPP-ERR60-b + + CERT_CPP-ERR60-a + + + CERT_CPP-ERR60-b + Exception objects must be nothrow copy constructible @@ -217,7 +376,9 @@ void f() { 4.4 - 3508 + + 3508 +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -274,7 +445,9 @@ void f() { diff --git a/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference-standard.qhelp b/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference-standard.qhelp index 86d608c149..d4acedd8f9 100644 --- a/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference-standard.qhelp +++ b/cpp/cert/src/rules/ERR61-CPP/CatchExceptionsByLvalueReference-standard.qhelp @@ -1,60 +1,233 @@
    -

    When an exception is thrown, the value of the object in the throw expression is used to initialize an anonymous temporary object called the exception object. The type of this exception object is used to transfer control to the nearest catch handler, which contains an exception declaration with a matching type. The C++ Standard, [except.handle], paragraph 16 [ISO/IEC 14882-2014], in part, states the following:

    +

    + When an exception is thrown, the value of the object in the throw expression is used to initialize an anonymous temporary object called the + + exception object + + . The type of this exception object is used to transfer control to the nearest catch handler,ย which contains an exception declaration with a matching type. The C++ Standard,ย [except.handle], paragraph 16 [ + + ISO/IEC 14882-2014 + + ],ย in part, states the following: +

    -

    The variable declared by the exception-declaration, of type cv T or cv T&, is initialized from the exception object, of type E, as follows: โ€” if T is a base class of E, the variable is copy-initialized from the corresponding base class subobject of the exception object; โ€” otherwise, the variable is copy-initialized from the exception object.

    +

    + The variable declared by the + + exception-declaration + + , of type + + cv + + + T + + or + + cv + + + T& + + , is initialized from the exceptionย object, of type + + E + + , as follows: + โ€” if + + T + + is a base class of + + E + + , the variable is copy-initialized from the corresponding base class subobjectย of the exception object; + โ€” otherwise, the variable is copy-initialized from the exception object. +

    -

    Because the variable declared by the exception-declaration is copy-initialized, it is possible to slice the exception object as part of the copy operation, losing valuable exception information and leading to incorrect error recovery. For more information about object slicing, see OOP51-CPP. Do not slice derived objects. Further, if the copy constructor of the exception object throws an exception, the copy initialization of the exception-declaration object results in undefined behavior. (See ERR60-CPP. Exception objects must be nothrow copy constructible for more information.)

    -

    Always catch exceptions by lvalue reference unless the type is a trivial type. For reference, the C++ Standard, [basic.types], paragraph 9 [ISO/IEC 14882-2014], defines trivial types as the following:

    +

    + Because the variable declared by the + + exception-declaration + + is copy-initialized, it is possible to + + slice + + + + the exception object as part of the copy operation, losing valuable exception information and leading to incorrect error recovery. + For more information about object slicing, see + + OOP51-CPP. Do not slice derived objects + + . Further, if the copy constructor of the exception object throws an exception, the copy initialization of the + + exception-declaration + + object results in undefined behavior. (See + + ERR60-CPP. Exception objects must be nothrow copy constructible + + for more information.) +

    +

    + Always catch exceptions by + + lvalue + + reference unless the type is a trivial type. For reference, the C++ Standard,ย [basic.types], paragraph 9 [ + + ISO/IEC 14882-2014 + + ], defines trivial types as the following: +

    -

    Arithmetic types, enumeration types, pointer types, pointer to member types, std::nullptr_t, and cv-qualified versions of these types are collectively called scalar types.... Scalar types, trivial class types, arrays of such types and cv-qualified versions of these types are collectively called trivial types.

    +

    + Arithmetic types, enumeration types, pointer types, pointer to member types, + + std::nullptr_t + + , and cv-qualified versions of these types are collectively called + + scalar types + + .... Scalarย types, trivial class types, arrays of such types and cv-qualified versions of these types areย collectively called + + trivial types + + . +

    -

    The C++ Standard, [class], paragraph 6, defines trivial class types as the following:

    +

    + The C++ Standard,ย [class], paragraph 6, defines trivial class types as the following: +

    -

    A trivially copyable class is a class that: โ€” has no non-trivial copy constructors, โ€” has no non-trivial move constructors, โ€” has no non-trivial copy assignment operators, โ€” has no non-trivial move assignment operators, and โ€” has a trivial destructor.A trivial class is a class that has a default constructor, has no non-trivial default constructors, and is trivially copyable. [Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base classes. โ€” end note]

    +

    + A + + trivially copyable class + + is a class that: + โ€” has no non-trivial copy constructors, + โ€” has no non-trivial move constructors, + โ€” has no non-trivial copy assignment operators, + โ€” has no non-trivial move assignment operators, and + โ€” has a trivial destructor. + A + + trivial class + + is a class that has a default constructor, has no non-trivial default constructors,ย and is trivially copyable.ย [ + + Note + + : In particular, a trivially copyable or trivial class does not have virtual functions or virtual baseย classes. โ€” + + end note + + ] +

    -

    In this noncompliant code example, an object of type S is used to initialize the exception object that is later caught by an exception-declaration of type std::exception. The exception-declaration matches the exception object type, so the variable E is copy-initialized from the exception object, resulting in the exception object being sliced. Consequently, the output of this noncompliant code example is the implementation-defined value returned from calling std::exception::what() instead of "My custom exception".

    - #include <exception> +

    + In this noncompliant code example, an object of type + + S + + is used to initialize the exception object that is later caught by an + + exception-declaration + + of type + + std::exception + + . The + + exception-declaration + + matches the exception object type, so the variable + + E + + is copy-initialized from the exception object, resulting in the exception object being sliced. Consequently, the output of this noncompliant code example is the implementation-defined value returned from calling + + std::exception::what() + + instead of + + "My custom exception" + + . +

    + + #include <exception> #include <iostream> - +ย  struct S : std::exception { const char *what() const noexcept override { return "My custom exception"; } }; - +ย  void f() { try { throw S(); } catch (std::exception e) { std::cout << e.what() << std::endl; } -} +} +
    -

    In this compliant solution, the variable declared by the exception-declaration is an lvalue reference. The call to what() results in executing S::what() instead of std::exception::what().

    - #include <exception> +

    + In this compliant solution, the variable declared by the + + exception-declaration + + is an lvalue reference. The call to + + what() + + results in executing + + S::what() + + instead of + + std::exception::what() + + . +

    + + #include <exception> #include <iostream> - +ย  struct S : std::exception { const char *what() const noexcept override { return "My custom exception"; } }; - +ย  void f() { try { throw S(); } catch (std::exception &e) { std::cout << e.what() << std::endl; } -} +} +
    -

    Object slicing can result in abnormal program execution. This generally is not a problem for exceptions, but it can lead to unexpected behavior depending on the assumptions made by the exception handler.

    +

    + Object slicing can result in abnormal program execution. This generally is not a problem for exceptions, but it can lead to unexpected behavior depending on the assumptions made by the exception handler. +

    Subclause 15.1, "Throwing an Exception" Subclause 18.8.1, "Class - exception + + exception + " Subclause 18.8.5, "Exception Propagation"
    @@ -91,10 +264,14 @@ void f() { Low @@ -127,7 +304,9 @@ void f() { 20.10 @@ -158,11 +339,15 @@ void f() { 3.9 @@ -195,7 +382,9 @@ void f() { 2021.4 @@ -209,7 +398,9 @@ void f() { @@ -273,10 +470,18 @@ void f() { @@ -291,7 +496,9 @@ void f() { 20.10 @@ -316,10 +527,27 @@ void f() {
    - P3 + + P3 + - L3 + + L3 +
    - catch-class-by-value + + catch-class-by-value + Fully checked @@ -143,7 +322,9 @@ void f() { 7.2.0 - CertC++-ERR61 + + CertC++-ERR61 + - cert-err61-cpp + + cert-err61-cpp + Checked by - clang-tidy + + clang-tidy + ; also checks for VOID ERR09-CPP. Throw anonymous temporaries @@ -180,7 +365,9 @@ void f() { 2021.2 - C++4031 + + C++4031 + - MISRA.CATCH.BY_VALUE + + MISRA.CATCH.BY_VALUE + - 455 S + + 455 S + Fully implemented @@ -225,8 +416,12 @@ void f() { 2021.2 - CERT_CPP-ERR61-a - CERT_CPP-ERR61-b + + CERT_CPP-ERR61-a + + + CERT_CPP-ERR61-b + A class type exception shall always be caught by reference @@ -261,7 +456,9 @@ void f() { 4.4 - 4031 + + 4031 + - 7.17 + 7.16 - V746, V816 + + + V746 + + , + + V816 + + - catch-class-by-value + + catch-class-by-value + Fully checked @@ -307,7 +514,11 @@ void f() { 4.10 - S1044 + + + S1044 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of OOP51-CPP. Do not slice derived objects.

    +

    + + This rule is a subset of + + OOP51-CPP. Do not slice derived objects. + + +

    diff --git a/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber-standard.qhelp b/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber-standard.qhelp index e9628787bf..3e12cc8f18 100644 --- a/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber-standard.qhelp +++ b/cpp/cert/src/rules/ERR62-CPP/DetectErrorsWhenConvertingAStringToANumber-standard.qhelp @@ -1,28 +1,159 @@
    -

    The process of parsing an integer or floating-point number from a string can produce many errors. The string might not contain a number. It might contain a number of the correct type that is out of range (such as an integer that is larger than INT_MAX). The string may also contain extra information after the number, which may or may not be useful after the conversion. These error conditions must be detected and addressed when a string-to-number conversion is performed using a formatted input stream such as std::istream or the locale facet num_get<>.

    -

    When calling a formatted input stream function like istream::operator>>(), information about conversion errors is queried through the basic_ios::good(), basic_ios::bad(), and basic_ios::fail() inherited member functions or through exception handling if it is enabled on the stream object.

    -

    When calling num_get<>::get(), information about conversion errors is returned to the caller through the ios_base::iostate& argument. The C++ Standard, section [facet.num.get.virtuals], paragraph 3 [ISO/IEC 14882-2014], in part, states the following:

    +

    + The process of parsing an integer or floating-point number from a string can produce many errors. The string might not contain a number. It might contain a number of the correct type that is out of range (such as an integer that is larger than + + INT_MAX + + ). The string may also contain extra information after the number, which may or may not be useful after the conversion. These error conditions must be detected and addressed when a string-to-number conversion is performed using a formatted input stream such as + + std::istream + + or the locale facet + + num_get<> + + . +

    +

    + When calling a formatted input stream function like + + istream::operator>>() + + , information about conversion errors is queried through the + + basic_ios::good() + + , + + basic_ios::bad() + + , and + + basic_ios::fail() + + inherited member functions or through exception handling if it is enabled on the stream object. +

    +

    + When calling + + num_get<>::get() + + , information about conversion errors is returned to the caller through the + + ios_base::iostate& + + argument. The C++ Standard, section [facet.num.get.virtuals], paragraph 3ย [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    If the conversion function fails to convert the entire field, or if the field represents a value outside the range of representable values, ios_base::failbit is assigned to err.

    +

    + If the conversion function fails to convert theย entire field, or if the field represents a value outside the range of representable values, + + ios_base::failbit + + is assigned to + + err + + . +

    -

    Always explicitly check the error state of a conversion from string to a numeric value (or handle the related exception, if applicable) instead of assuming the conversion results in a valid value. This rule is in addition to ERR34-C. Detect errors when converting a string to a number, which bans the use of conversion functions that do not perform conversion validation such as std::atoi() and std::scanf() from the C Standard Library.

    +

    + Always explicitly check the error state of a conversion from string to a numeric value (or handle the related exception, if applicable) instead of assuming the conversion results in a valid value. This rule is in addition to + + ERR34-C. Detect errors when converting a string to a number + + , which bans the use of conversion functions that do not perform conversion validation such as + + std::atoi() + + and + + std::scanf() + + from the C Standard Library. +

    -

    In this noncompliant code example, multiple numeric values are converted from the standard input stream. However, if the text received from the standard input stream cannot be converted into a numeric value that can be represented by an int, the resulting value stored into the variables i and j may be unexpected.

    - #include <iostream> +

    + In this noncompliant code example, multiple numeric values are converted from the standard input stream. However, if the text received from the standard input stream cannot be converted into a numeric value that can be represented by an + + int + + , the resulting value stored into the variables + + i + + and + + j + + may be unexpected. +

    + + #include <iostream> void f() { int i, j; std::cin >> i >> j; // ... -} -

    For instance, if the text 12345678901234567890 is the first converted value read from the standard input stream, then i will have the value std::numeric_limits<int>::max() (per [facet.num.get.virtuals] paragraph 3), and j will be uninitialized (per [istream.formatted.arithmetic] paragraph 3). If the text abcdefg is the first converted value read from the standard input stream, then i will have the value 0 and j will remain uninitialized.

    +} +
    +

    + For instance, if the text + + 12345678901234567890 + + is the first converted value read from the standard input stream, then + + i + + will have the value + + std::numeric_limits<int>::max() + + (perย [facet.num.get.virtuals] paragraph 3), and + + j + + will be uninitialized (perย [istream.formatted.arithmetic] paragraph 3). If the text + + abcdefg + + is the first converted value read from the standard input stream, then + + i + + will have the value + + 0 + + and + + j + + will remain uninitialized. +

    -

    In this compliant solution, exceptions are enabled so that any conversion failure results in an exception being thrown. However, this approach cannot distinguish between which values are valid and which values are invalid and must assume that all values are invalid. Both the badbit and failbit flags are set to ensure that conversion errors as well as loss of integrity with the stream are treated as exceptions.

    - #include <iostream> +

    + In this compliant solution, exceptions are enabled so that any conversion failure results in an exception being thrown. However, this approach cannot distinguish between which values are valid and which values are invalid and must assume that all values are invalid. Both the + + badbit + + and + + failbit + + flags are set to ensure that conversion errors as well as loss of integrity with the stream are treated as exceptions. +

    + + #include <iostream> void f() { int i, j; @@ -34,11 +165,23 @@ void f() { } catch (std::istream::failure &E) { // Handle error } -} +} +
    -

    In this compliant solution, each converted value read from the standard input stream is tested for validity before reading the next value in the sequence, allowing error recovery on a per-value basis. It checks std::istream::fail() to see if the failure bit was set due to a conversion failure or whether the bad bit was set due to a loss of integrity with the stream object. If a failure condition is encountered, it is cleared on the input stream and then characters are read and discarded until a ' ' (space) character occurs. The error handling in this case only works if a space character is what delimits the two numeric values to be converted.

    - #include <iostream> +

    + In this compliant solution, each converted value read from the standard input stream is tested for validity before reading the next value in the sequence, allowing error recovery on a per-value basis. It checks + + std::istream::fail() + + to see if the failure bit was set due to a conversion failure or whether the bad bit was set due to a loss of integrity with the stream object. If aย failure condition is encountered, it is cleared on the input stream and then characters are read and discarded until a + + ' ' + + (space) characterย occurs.ย The error handling in this case only works if a space character is what delimits the two numeric values to be converted. +

    + + #include <iostream> #include <limits> void f() { @@ -56,12 +199,19 @@ void f() { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), ' '); } - +ย  // ... -} +} +
    -

    It is rare for a violation of this rule to result in a security vulnerability unless it occurs in security-sensitive code. However, violations of this rule can easily result in lost or misinterpreted data.

    +

    + It is rare for a violation of this rule to result in a security + + vulnerability + + unless it occurs in security-sensitive code. However, violations of this ruleย can easily result in lost or misinterpreted data. +

    @@ -98,10 +248,14 @@ void f() { Medium @@ -134,7 +288,9 @@ void f() { 7.2.0 @@ -149,11 +305,15 @@ void f() { 3.9 @@ -164,10 +324,21 @@ void f() { @@ -201,7 +374,11 @@ void f() { 2021.4 @@ -216,7 +393,9 @@ void f() { 2021.2
    - P4 + + P4 + - L3 + + L3 +
    - CertC++-ERR62 + + CertC++-ERR62 + - cert-err34-c + + cert-err34-c + Checked by - clang-tidy + + clang-tidy + ; only identifies use of unsafe C Standard Library functions corresponding to ERR34-C
    - 6.2p0 + 6.1p0 - BADFUNC.ATOFBADFUNC.ATOIBADFUNC.ATOFBADFUNC.ATOF + + BADFUNC.ATOF + + BADFUNC.ATOI + + + BADFUNC.ATOF + + + BADFUNC.ATOF + + Use of atof @@ -186,7 +357,9 @@ void f() { 2021.2 - C++3161 + + C++3161 + - CERT.ERR.CONV.STR_TO_NUM + + + CERT.ERR.CONV.STR_TO_NUM + + - CERT_CPP-ERR62-a + + CERT_CPP-ERR62-a + The library functions atof, atoi and atol from library stdlib.h shall not be used @@ -226,7 +405,17 @@ void f() {
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments-standard.qhelp b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments-standard.qhelp index cb9f3b81df..f9997e79a2 100644 --- a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments-standard.qhelp +++ b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments-standard.qhelp @@ -1,115 +1,401 @@
    -

    In C++, modifying an object, calling a library I/O function, accessing a volatile-qualified value, or calling a function that performs one of these actions are ways to modify the state of the execution environment. These actions are called side effects. All relationships between value computations and side effects can be described in terms of sequencing of their evaluations. The C++ Standard, [intro.execution], paragraph 13 [ISO/IEC 14882-2014], establishes three sequencing terms:

    +

    + In C++, modifying an object, calling a library I/O function, accessing a + + volatile + + -qualified value, or calling a function that performs one of these actions are ways to modify the state of the execution environment. These actions are called + + side effects + + . All relationships between value computations and side effects can be described in terms of sequencing of their evaluations. The C++ Standard,ย [intro.execution], paragraph 13ย [ + + ISO/IEC 14882-2014 + + ], establishes three sequencing terms: +

    -

    Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread, which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [Note: The execution of unsequenced evaluations can overlap. โ€” end note] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. โ€” end note]

    +

    + + Sequenced before + + is an asymmetric, transitive, pair-wise relation between evaluations executed by a singleย thread,ย which induces a partial order among those evaluations.ย Given any two evaluations + + A + + and + + B + + , if + + A + + is sequenced before + + B + + , then the execution of + + A + + shall precede the execution of + + B + + . If + + A + + is not sequenced before + + B + + and + + B + + is not sequenced before + + A + + , then + + A + + and + + B + + are + + unsequenced + + . [Note: The execution of unsequencedย evaluations can overlap. โ€” end note] Evaluations + + A + + and + + B + + are + + indeterminately sequenced + + when either + + A + + is sequenced before + + B + + or + + B + + is sequenced before + + A + + , but it is unspecified which. [Note: Indeterminatelyย sequenced evaluations cannot overlap, but either could be executed first. โ€” end note] +

    -

    Paragraph 15 further states (nonnormative text removed for brevity) the following:

    +

    + Paragraph 15 further states (nonnormative text removed for brevity) the following: +

    -

    Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. ... The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent, the behavior is undefined. ... When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. ... Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function. Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. ... The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be.

    +

    + Except where noted, evaluations of operands of individual operators and of subexpressions of individualย expressions are unsequenced. ...ย The value computations of the operands of anย operator are sequenced before the value computation of the result of the operator. If a side effect on a scalarย object is unsequenced relative to either another side effect on the same scalar object or a value computationย using the value of the same scalar object, and they are not potentially concurrent, the behavior isย undefined. ...ย When calling a function (whether or not the function is inline), every value computation and side effectย associated with any argument expression, or with the postfix expression designating the called function, isย sequenced before execution of every expression or statement in the body of the called function. ...ย Every evaluation in the calling function (including other function calls) that is not otherwise specificallyย sequenced before or after the execution of the body of the called function is indeterminately sequenced withย respect to the execution of the called function. Several contexts in C++ cause evaluation of a function call,ย even though no corresponding function call syntax appears in the translation unit. ...ย The sequencing constraints on the execution of the called function (as described above)ย are features of the function calls as evaluated, whatever the syntax of the expression that calls the functionย might be. +

    -

    Do not allow the same scalar object to appear in side effects or value computations in both halves of an unsequenced or indeterminately sequenced operation.

    -

    The following expressions have sequencing restrictions that deviate from the usual unsequenced ordering [ISO/IEC 14882-2014]:

    +

    + Do not allow the same scalar object to appear in side effects or value computations in both halves of an unsequenced or indeterminately sequenced operation. +

    +

    + The following expressions have sequencing restrictions that deviate from the usual unsequenced ordering [ + + ISO/IEC 14882-2014 + + ]: +

      -
    • In postfix ++ and -- expressions, the value computation is sequenced before the modification of the operand. ([expr.post.incr], paragraph 1)
    • -
    • In logical && expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.and], paragraph 2)
    • -
    • In logical || expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.or], paragraph 2)
    • -
    • In conditional ?: expressions, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression (whichever is evaluated). ([expr.cond], paragraph 1)
    • -
    • In assignment expressions (including compound assignments), the assignment is sequenced after the value computations of left and right operands and before the value computation of the assignment expression. ([expr.ass], paragraph 1)
    • -
    • In comma , expressions, every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. ([expr.comma], paragraph 1)
    • -
    • When evaluating initializer lists, the value computation and side effect associated with each initializer-clause is sequenced before every value computation and side effect associated with a subsequent initializer-clause. ([dcl.init.list], paragraph 4)
    • -
    • When a signal handler is executed as a result of a call to std::raise(), the execution of the handler is sequenced after the invocation of std::raise() and before its return. ([intro.execution], paragraph 6)
    • -
    • The completions of the destructors for all initialized objects with thread storage duration within a thread are sequenced before the initiation of the destructors of any object with static storage duration. ([basic.start.term], paragraph 1)
    • -
    • In a new-expression, initialization of an allocated object is sequenced before the value computation of the new-expression. ([expr.new], paragraph 18)
    • -
    • When a default constructor is called to initialize an element of an array and the constructor has at least one default argument, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any. ([class.temporary], paragraph 4)
    • -
    • The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary that is constructed earlier in the same full-expression. ([class.temporary], paragraph 5)
    • -
    • Atomic memory ordering functions can explicitly determine the sequencing order for expressions. ([atomics.order] and [atomics.fences])
    • +
    • + In postfix + + ++ + + and + + -- + + expressions, the value computation is sequenced before the modification of the operand. ([expr.post.incr], paragraph 1) +
    • +
    • + In logical + + && + + expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.and], paragraph 2) +
    • +
    • + Inย logical + + || + + expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.or], paragraph 2) +
    • +
    • + Inย conditional + + ?: + + expressions, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression (whichever is evaluated). ([expr.cond], paragraph 1) +
    • +
    • + In assignment expressions (including compound assignments), the assignment is sequenced after the value computations of left and right operands and before the value computation of the assignment expression. ([expr.ass], paragraph 1) +
    • +
    • + In comma + + , + + expressions, every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. ([expr.comma], paragraph 1) +
    • +
    • + When evaluating initializer lists, the value computation and side effect associated with each + + initializer-clause + + is sequenced before every value computation and side effect associated with a subsequent + + initializer-clause + + . ([dcl.init.list], paragraph 4) +
    • +
    • + When a signal handler is executed as a result of a call to + + std::raise() + + , the execution of the handler is sequenced after the invocation of + + std::raise() + + and before its return. ([intro.execution], paragraph 6) +
    • +
    • + The completionsย of the destructors for all initialized objects with thread storage duration within a thread are sequencedย before the initiation of the destructors of any object with static storage duration. ([basic.start.term], paragraph 1) +
    • +
    • + In a + + new-expression + + , initialization of an allocated object is sequenced before the value computation of the + + new-expression + + . ([expr.new], paragraph 18) +
    • +
    • + When a default constructor is called to initialize an element of an array and the constructor has at least one default argument, theย destruction of every temporary created in a defaultย argument is sequenced before the construction of the next array element, if any.ย ([class.temporary], paragraph 4) +
    • +
    • + The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequencedย before the destruction of every temporary that is constructed earlier in the same full-expression. ([class.temporary], paragraph 5) +
    • +
    • + Atomic memory ordering functions can explicitly determine the sequencing order for expressions. ([atomics.order] andย [atomics.fences]) +
    -

    This rule means that statements such as

    - i = i + 1; +

    + This rule means that statements such as +

    + + i = i + 1; a[i] = i; - -

    have defined behavior, and statements such as the following do not.

    - // i is modified twice in the same full expression + +

    + have defined behavior,ย and statements such as the following do not. +

    + + // i is modified twice in the same full expression i = ++i + 1; // i is read other than to determine the value to be stored -a[i++] = i; - -

    Not all instances of a comma in C++ code denote use of the comma operator. For example, the comma between arguments in a function call is not the comma operator. Additionally, overloaded operators behave the same as a function call, with the operands to the operator acting as arguments to a function call.

    +a[i++] = i; +
    +

    + Not all instances of a comma in C++ code denote use of the comma operator. For example, the comma between arguments in a function call is + + not + + the comma operator.ย Additionally, overloaded operators behave the same as a function call, with the operands to the operator acting as arguments to a function call. +

    -

    In this noncompliant code example, i is evaluated more than once in an unsequenced manner, so the behavior of the expression is undefined.

    - void f(int i, const int *b) { +

    + In this noncompliant code example, + + i + + is evaluated more than once in an unsequenced manner, so the behavior of the expression is + + undefined + + . +

    + + void f(int i, const int *b) { int a = i + b[++i]; // ... } - +
    -

    These examples are independent of the order of evaluation of the operands and can each be interpreted in only one way.

    - void f(int i, const int *b) { +

    + These examples are independent of the order of evaluation of the operands and can each be interpreted in only one way. +

    + + void f(int i, const int *b) { ++i; int a = i + b[i]; // ... } - - void f(int i, const int *b) { + + + void f(int i, const int *b) { int a = i + b[i + 1]; ++i; // ... } - +
    -

    The call to func() in this noncompliant code example has undefined behavior because the argument expressions are unsequenced.

    - extern void func(int i, int j); +

    + The call to + + func() + + in this noncompliant code example has + + undefined behavior + + because the argument expressions are unsequenced. +

    + + extern void func(int i, int j); void f(int i) { func(i++, i); } - -

    The first (left) argument expression reads the value of i (to determine the value to be stored) and then modifies i. The second (right) argument expression reads the value of i, but not to determine the value to be stored in i. This additional attempt to read the value of i has undefined behavior.

    +
    +

    + The first (left) argument expression reads the value of + + i + + (to determine the value to be stored) and then modifies + + i + + . The second (right) argument expression reads the value of + + i + + ,ย but not to determine the value to be stored in + + i + + . This additional attempt to read the value of + + i + + has + + undefined behavior + + . +

    -

    This compliant solution is appropriate when the programmer intends for both arguments to func() to be equivalent.

    - extern void func(int i, int j); +

    + This compliant solution is appropriate when the programmer intends for both arguments to + + func() + + to be equivalent. +

    + + extern void func(int i, int j); void f(int i) { i++; func(i, i); } - -

    This compliant solution is appropriate when the programmer intends for the second argument to be 1 greater than the first.

    - extern void func(int i, int j); + +

    + This compliant solution is appropriate when the programmer intends for the second argument to be 1 greater than the first. +

    + + extern void func(int i, int j); void f(int i) { int j = i++; func(j, i); } - +
    -

    This noncompliant code example is similar to the previous noncompliant code example. However, instead of calling a function directly, this code calls an overloaded operator<<(). Overloaded operators are equivalent to a function call and have the same restrictions regarding the sequencing of the function call arguments. This means that the operands are not evaluated left-to-right, but are unsequenced with respect to one another. Consequently, this noncompliant code example has undefined behavior.

    - #include <iostream> +

    + This noncompliant code example is similar to the previous noncompliant code example. However, instead of calling a function directly, this code calls an overloaded + + operator<<() + + . Overloaded operators are equivalent to a function call and have the same restrictions regarding the sequencing of the function call arguments. This means that the operands are not evaluated left-to-right, but are unsequenced with respect to one another. Consequently, this noncompliant code example has undefined behavior. +

    + + #include <iostream> void f(int i) { std::cout << i++ << i << std::endl; -} +} +
    -

    In this compliant solution, two calls are made to operator<<(), ensuring that the arguments are printed in a well-defined order.

    - #include <iostream> - +

    + In this compliant solution, two calls are made to + + operator<<() + + , ensuring that the arguments are printed in a well-defined order. +

    + + #include <iostream> +ย  void f(int i) { std::cout << i++; std::cout << i << std::endl; -} +} +
    -

    The order of evaluation for function arguments is unspecified. This noncompliant code example exhibits unspecified behavior but not undefined behavior.

    - extern void c(int i, int j); +

    + The order of evaluation for function arguments is unspecified. This noncompliant code example exhibits + + unspecified behavior + + but not + + undefined behavior + + . +

    + + extern void c(int i, int j); int glob; int a() { @@ -124,12 +410,61 @@ int b() { void f() { c(a(), b()); } - -

    The order in which a() and b() are called is unspecified; the only guarantee is that both a() and b() will be called before c() is called. If a() or b() rely on shared state when calculating their return value, as they do in this example, the resulting arguments passed to c() may differ between compilers or architectures.

    +
    +

    + The order in which + + a() + + and + + b() + + are called is unspecified; the only guarantee is that both + + a() + + and + + b() + + will be called before + + c() + + is called. If + + a() + + or + + b() + + rely on shared state when calculating their return value, as they do in this example, the resulting arguments passed to + + c() + + may differ between compilers or architectures. +

    -

    In this compliant solution, the order of evaluation for a() and b() is fixed, and so no unspecified behavior occurs.

    - extern void c(int i, int j); +

    + In this compliant solution, the order of evaluation for + + a() + + and + + b() + + is fixed, and so no + + unspecified behavior + + occurs. +

    + + extern void c(int i, int j); int glob; int a() { @@ -149,10 +484,14 @@ void f() { c(a_val, b_val); } - +
    -

    Attempting to modify an object in an unsequenced or indeterminately sequenced evaluation may cause that object to take on an unexpected value, which can lead to unexpected program behavior.

    +

    + Attempting to modify an object in an unsequenced or indeterminately sequenced evaluation may cause that object to take on an unexpected value, which can lead to + unexpected program behavior + . +

    @@ -189,10 +528,14 @@ void f() { Medium @@ -225,7 +568,9 @@ void f() { 7.2.0 @@ -240,7 +585,9 @@ void f() { 3.9 @@ -270,7 +617,9 @@ void f() { v7.5.0 @@ -318,7 +671,9 @@ void f() { 2021.2 @@ -333,11 +688,31 @@ void f() { 2021.4 @@ -351,10 +726,18 @@ void f() { @@ -426,12 +823,20 @@ void f() { @@ -446,7 +851,11 @@ void f() { 4.10
    - P8 + + P8 + - L2 + + L2 +
    - CertC++-EXP50 + + CertC++-EXP50 + - -Wunsequenced + + -Wunsequenced + Can detect simple violations of this rule where path-sensitive analysis is not required @@ -257,7 +604,7 @@ void f() { - Can detect simple violations of this rule. It needs to examine each expression and make sure that no variable is modified twice in the expression. It also must check that no variable is modified once, then read elsewhere, with the single exception that a variable may appear on both the left and right of an assignment operator + Can detect simple violations of this rule. It needs to examine each expression and make sure that no variable is modified twice in the expression.ย It also mustย check thatย no variable is modified once, then read elsewhere, with the single exception that a variable may appear on both the left and right of an assignment operator
    - EVALUATION_ORDER + + EVALUATION_ORDER + Can detect the specific instance where a statement contains multiple side effects on the same value with an undefined evaluation order because, with different compiler flags or different compilers or platforms, the statement may behave differently @@ -286,7 +635,9 @@ void f() { 1.2 - CC2.EXP30 + + CC2.EXP30 + Fully implemented @@ -304,7 +655,9 @@ void f() { Can detect violations of this rule when the - -Wsequence-point + + -Wsequence-point + flag is used
    - C++3220, C++3221, C++3222, C++3223, C++3228 + + C++3220, C++3221, C++3222, C++3223, C++3228 + - PORTING.VAR.EFFECTS - MISRA.EXPR.PARENS - MISRA.EXPR.PARENS.INSUFFICIENT - MISRA.EXPR.PARENS.REDUNDANT - MISRA.INCR_DECR.OTHER + + + PORTING.VAR.EFFECTS + + + + + MISRA.EXPR.PARENS + + + + + MISRA.EXPR.PARENS.INSUFFICIENT + + + + + MISRA.EXPR.PARENS.REDUNDANT + + + + + MISRA.INCR_DECR.OTHER + + - 35 D - , 1 Q - , 9 S - , 134 S, 67 D, 72 D + + 35 D + + + , 1 Q + + + , 9 S + + + , 134 S, 67 D, 72 D + Partially implemented @@ -370,12 +753,24 @@ void f() { 2021.2 - CERT_CPP-EXP50-a - CERT_CPP-EXP50-b - CERT_CPP-EXP50-c - CERT_CPP-EXP50-d - CERT_CPP-EXP50-e - CERT_CPP-EXP50-f + + CERT_CPP-EXP50-a + + + CERT_CPP-EXP50-b + + + CERT_CPP-EXP50-c + + + CERT_CPP-EXP50-d + + + CERT_CPP-EXP50-e + + + CERT_CPP-EXP50-f + The value of an expression shall be the same under any order of evaluation that the standard permits @@ -414,7 +809,9 @@ void f() { 4.4 - 3220, 3221, 3222, 3223, 3228 + + 3220, 3221, 3222, 3223, 3228 + - 7.17 + 7.16 - V521 + + V521 + + + , - V708 + + + V708 + + - IncAndDecMixedWithOtherOperators + + + IncAndDecMixedWithOtherOperators + + Partially implemented @@ -469,7 +878,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects-standard.qhelp b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects-standard.qhelp index cb9f3b81df..f9997e79a2 100644 --- a/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects-standard.qhelp +++ b/cpp/cert/src/rules/EXP50-CPP/DoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects-standard.qhelp @@ -1,115 +1,401 @@
    -

    In C++, modifying an object, calling a library I/O function, accessing a volatile-qualified value, or calling a function that performs one of these actions are ways to modify the state of the execution environment. These actions are called side effects. All relationships between value computations and side effects can be described in terms of sequencing of their evaluations. The C++ Standard, [intro.execution], paragraph 13 [ISO/IEC 14882-2014], establishes three sequencing terms:

    +

    + In C++, modifying an object, calling a library I/O function, accessing a + + volatile + + -qualified value, or calling a function that performs one of these actions are ways to modify the state of the execution environment. These actions are called + + side effects + + . All relationships between value computations and side effects can be described in terms of sequencing of their evaluations. The C++ Standard,ย [intro.execution], paragraph 13ย [ + + ISO/IEC 14882-2014 + + ], establishes three sequencing terms: +

    -

    Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread, which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [Note: The execution of unsequenced evaluations can overlap. โ€” end note] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. โ€” end note]

    +

    + + Sequenced before + + is an asymmetric, transitive, pair-wise relation between evaluations executed by a singleย thread,ย which induces a partial order among those evaluations.ย Given any two evaluations + + A + + and + + B + + , if + + A + + is sequenced before + + B + + , then the execution of + + A + + shall precede the execution of + + B + + . If + + A + + is not sequenced before + + B + + and + + B + + is not sequenced before + + A + + , then + + A + + and + + B + + are + + unsequenced + + . [Note: The execution of unsequencedย evaluations can overlap. โ€” end note] Evaluations + + A + + and + + B + + are + + indeterminately sequenced + + when either + + A + + is sequenced before + + B + + or + + B + + is sequenced before + + A + + , but it is unspecified which. [Note: Indeterminatelyย sequenced evaluations cannot overlap, but either could be executed first. โ€” end note] +

    -

    Paragraph 15 further states (nonnormative text removed for brevity) the following:

    +

    + Paragraph 15 further states (nonnormative text removed for brevity) the following: +

    -

    Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. ... The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent, the behavior is undefined. ... When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. ... Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function. Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. ... The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be.

    +

    + Except where noted, evaluations of operands of individual operators and of subexpressions of individualย expressions are unsequenced. ...ย The value computations of the operands of anย operator are sequenced before the value computation of the result of the operator. If a side effect on a scalarย object is unsequenced relative to either another side effect on the same scalar object or a value computationย using the value of the same scalar object, and they are not potentially concurrent, the behavior isย undefined. ...ย When calling a function (whether or not the function is inline), every value computation and side effectย associated with any argument expression, or with the postfix expression designating the called function, isย sequenced before execution of every expression or statement in the body of the called function. ...ย Every evaluation in the calling function (including other function calls) that is not otherwise specificallyย sequenced before or after the execution of the body of the called function is indeterminately sequenced withย respect to the execution of the called function. Several contexts in C++ cause evaluation of a function call,ย even though no corresponding function call syntax appears in the translation unit. ...ย The sequencing constraints on the execution of the called function (as described above)ย are features of the function calls as evaluated, whatever the syntax of the expression that calls the functionย might be. +

    -

    Do not allow the same scalar object to appear in side effects or value computations in both halves of an unsequenced or indeterminately sequenced operation.

    -

    The following expressions have sequencing restrictions that deviate from the usual unsequenced ordering [ISO/IEC 14882-2014]:

    +

    + Do not allow the same scalar object to appear in side effects or value computations in both halves of an unsequenced or indeterminately sequenced operation. +

    +

    + The following expressions have sequencing restrictions that deviate from the usual unsequenced ordering [ + + ISO/IEC 14882-2014 + + ]: +

      -
    • In postfix ++ and -- expressions, the value computation is sequenced before the modification of the operand. ([expr.post.incr], paragraph 1)
    • -
    • In logical && expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.and], paragraph 2)
    • -
    • In logical || expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.or], paragraph 2)
    • -
    • In conditional ?: expressions, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression (whichever is evaluated). ([expr.cond], paragraph 1)
    • -
    • In assignment expressions (including compound assignments), the assignment is sequenced after the value computations of left and right operands and before the value computation of the assignment expression. ([expr.ass], paragraph 1)
    • -
    • In comma , expressions, every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. ([expr.comma], paragraph 1)
    • -
    • When evaluating initializer lists, the value computation and side effect associated with each initializer-clause is sequenced before every value computation and side effect associated with a subsequent initializer-clause. ([dcl.init.list], paragraph 4)
    • -
    • When a signal handler is executed as a result of a call to std::raise(), the execution of the handler is sequenced after the invocation of std::raise() and before its return. ([intro.execution], paragraph 6)
    • -
    • The completions of the destructors for all initialized objects with thread storage duration within a thread are sequenced before the initiation of the destructors of any object with static storage duration. ([basic.start.term], paragraph 1)
    • -
    • In a new-expression, initialization of an allocated object is sequenced before the value computation of the new-expression. ([expr.new], paragraph 18)
    • -
    • When a default constructor is called to initialize an element of an array and the constructor has at least one default argument, the destruction of every temporary created in a default argument is sequenced before the construction of the next array element, if any. ([class.temporary], paragraph 4)
    • -
    • The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequenced before the destruction of every temporary that is constructed earlier in the same full-expression. ([class.temporary], paragraph 5)
    • -
    • Atomic memory ordering functions can explicitly determine the sequencing order for expressions. ([atomics.order] and [atomics.fences])
    • +
    • + In postfix + + ++ + + and + + -- + + expressions, the value computation is sequenced before the modification of the operand. ([expr.post.incr], paragraph 1) +
    • +
    • + In logical + + && + + expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.and], paragraph 2) +
    • +
    • + Inย logical + + || + + expressions, if the second expression is evaluated, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second expression. ([expr.log.or], paragraph 2) +
    • +
    • + Inย conditional + + ?: + + expressions, every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression (whichever is evaluated). ([expr.cond], paragraph 1) +
    • +
    • + In assignment expressions (including compound assignments), the assignment is sequenced after the value computations of left and right operands and before the value computation of the assignment expression. ([expr.ass], paragraph 1) +
    • +
    • + In comma + + , + + expressions, every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. ([expr.comma], paragraph 1) +
    • +
    • + When evaluating initializer lists, the value computation and side effect associated with each + + initializer-clause + + is sequenced before every value computation and side effect associated with a subsequent + + initializer-clause + + . ([dcl.init.list], paragraph 4) +
    • +
    • + When a signal handler is executed as a result of a call to + + std::raise() + + , the execution of the handler is sequenced after the invocation of + + std::raise() + + and before its return. ([intro.execution], paragraph 6) +
    • +
    • + The completionsย of the destructors for all initialized objects with thread storage duration within a thread are sequencedย before the initiation of the destructors of any object with static storage duration. ([basic.start.term], paragraph 1) +
    • +
    • + In a + + new-expression + + , initialization of an allocated object is sequenced before the value computation of the + + new-expression + + . ([expr.new], paragraph 18) +
    • +
    • + When a default constructor is called to initialize an element of an array and the constructor has at least one default argument, theย destruction of every temporary created in a defaultย argument is sequenced before the construction of the next array element, if any.ย ([class.temporary], paragraph 4) +
    • +
    • + The destruction of a temporary whose lifetime is not extended by being bound to a reference is sequencedย before the destruction of every temporary that is constructed earlier in the same full-expression. ([class.temporary], paragraph 5) +
    • +
    • + Atomic memory ordering functions can explicitly determine the sequencing order for expressions. ([atomics.order] andย [atomics.fences]) +
    -

    This rule means that statements such as

    - i = i + 1; +

    + This rule means that statements such as +

    + + i = i + 1; a[i] = i; - -

    have defined behavior, and statements such as the following do not.

    - // i is modified twice in the same full expression + +

    + have defined behavior,ย and statements such as the following do not. +

    + + // i is modified twice in the same full expression i = ++i + 1; // i is read other than to determine the value to be stored -a[i++] = i; - -

    Not all instances of a comma in C++ code denote use of the comma operator. For example, the comma between arguments in a function call is not the comma operator. Additionally, overloaded operators behave the same as a function call, with the operands to the operator acting as arguments to a function call.

    +a[i++] = i; +
    +

    + Not all instances of a comma in C++ code denote use of the comma operator. For example, the comma between arguments in a function call is + + not + + the comma operator.ย Additionally, overloaded operators behave the same as a function call, with the operands to the operator acting as arguments to a function call. +

    -

    In this noncompliant code example, i is evaluated more than once in an unsequenced manner, so the behavior of the expression is undefined.

    - void f(int i, const int *b) { +

    + In this noncompliant code example, + + i + + is evaluated more than once in an unsequenced manner, so the behavior of the expression is + + undefined + + . +

    + + void f(int i, const int *b) { int a = i + b[++i]; // ... } - +
    -

    These examples are independent of the order of evaluation of the operands and can each be interpreted in only one way.

    - void f(int i, const int *b) { +

    + These examples are independent of the order of evaluation of the operands and can each be interpreted in only one way. +

    + + void f(int i, const int *b) { ++i; int a = i + b[i]; // ... } - - void f(int i, const int *b) { + + + void f(int i, const int *b) { int a = i + b[i + 1]; ++i; // ... } - +
    -

    The call to func() in this noncompliant code example has undefined behavior because the argument expressions are unsequenced.

    - extern void func(int i, int j); +

    + The call to + + func() + + in this noncompliant code example has + + undefined behavior + + because the argument expressions are unsequenced. +

    + + extern void func(int i, int j); void f(int i) { func(i++, i); } - -

    The first (left) argument expression reads the value of i (to determine the value to be stored) and then modifies i. The second (right) argument expression reads the value of i, but not to determine the value to be stored in i. This additional attempt to read the value of i has undefined behavior.

    +
    +

    + The first (left) argument expression reads the value of + + i + + (to determine the value to be stored) and then modifies + + i + + . The second (right) argument expression reads the value of + + i + + ,ย but not to determine the value to be stored in + + i + + . This additional attempt to read the value of + + i + + has + + undefined behavior + + . +

    -

    This compliant solution is appropriate when the programmer intends for both arguments to func() to be equivalent.

    - extern void func(int i, int j); +

    + This compliant solution is appropriate when the programmer intends for both arguments to + + func() + + to be equivalent. +

    + + extern void func(int i, int j); void f(int i) { i++; func(i, i); } - -

    This compliant solution is appropriate when the programmer intends for the second argument to be 1 greater than the first.

    - extern void func(int i, int j); + +

    + This compliant solution is appropriate when the programmer intends for the second argument to be 1 greater than the first. +

    + + extern void func(int i, int j); void f(int i) { int j = i++; func(j, i); } - +
    -

    This noncompliant code example is similar to the previous noncompliant code example. However, instead of calling a function directly, this code calls an overloaded operator<<(). Overloaded operators are equivalent to a function call and have the same restrictions regarding the sequencing of the function call arguments. This means that the operands are not evaluated left-to-right, but are unsequenced with respect to one another. Consequently, this noncompliant code example has undefined behavior.

    - #include <iostream> +

    + This noncompliant code example is similar to the previous noncompliant code example. However, instead of calling a function directly, this code calls an overloaded + + operator<<() + + . Overloaded operators are equivalent to a function call and have the same restrictions regarding the sequencing of the function call arguments. This means that the operands are not evaluated left-to-right, but are unsequenced with respect to one another. Consequently, this noncompliant code example has undefined behavior. +

    + + #include <iostream> void f(int i) { std::cout << i++ << i << std::endl; -} +} +
    -

    In this compliant solution, two calls are made to operator<<(), ensuring that the arguments are printed in a well-defined order.

    - #include <iostream> - +

    + In this compliant solution, two calls are made to + + operator<<() + + , ensuring that the arguments are printed in a well-defined order. +

    + + #include <iostream> +ย  void f(int i) { std::cout << i++; std::cout << i << std::endl; -} +} +
    -

    The order of evaluation for function arguments is unspecified. This noncompliant code example exhibits unspecified behavior but not undefined behavior.

    - extern void c(int i, int j); +

    + The order of evaluation for function arguments is unspecified. This noncompliant code example exhibits + + unspecified behavior + + but not + + undefined behavior + + . +

    + + extern void c(int i, int j); int glob; int a() { @@ -124,12 +410,61 @@ int b() { void f() { c(a(), b()); } - -

    The order in which a() and b() are called is unspecified; the only guarantee is that both a() and b() will be called before c() is called. If a() or b() rely on shared state when calculating their return value, as they do in this example, the resulting arguments passed to c() may differ between compilers or architectures.

    +
    +

    + The order in which + + a() + + and + + b() + + are called is unspecified; the only guarantee is that both + + a() + + and + + b() + + will be called before + + c() + + is called. If + + a() + + or + + b() + + rely on shared state when calculating their return value, as they do in this example, the resulting arguments passed to + + c() + + may differ between compilers or architectures. +

    -

    In this compliant solution, the order of evaluation for a() and b() is fixed, and so no unspecified behavior occurs.

    - extern void c(int i, int j); +

    + In this compliant solution, the order of evaluation for + + a() + + and + + b() + + is fixed, and so no + + unspecified behavior + + occurs. +

    + + extern void c(int i, int j); int glob; int a() { @@ -149,10 +484,14 @@ void f() { c(a_val, b_val); } - +
    -

    Attempting to modify an object in an unsequenced or indeterminately sequenced evaluation may cause that object to take on an unexpected value, which can lead to unexpected program behavior.

    +

    + Attempting to modify an object in an unsequenced or indeterminately sequenced evaluation may cause that object to take on an unexpected value, which can lead to + unexpected program behavior + . +

    @@ -189,10 +528,14 @@ void f() { Medium @@ -225,7 +568,9 @@ void f() { 7.2.0 @@ -240,7 +585,9 @@ void f() { 3.9 @@ -270,7 +617,9 @@ void f() { v7.5.0 @@ -318,7 +671,9 @@ void f() { 2021.2 @@ -333,11 +688,31 @@ void f() { 2021.4 @@ -351,10 +726,18 @@ void f() { @@ -426,12 +823,20 @@ void f() { @@ -446,7 +851,11 @@ void f() { 4.10
    - P8 + + P8 + - L2 + + L2 +
    - CertC++-EXP50 + + CertC++-EXP50 + - -Wunsequenced + + -Wunsequenced + Can detect simple violations of this rule where path-sensitive analysis is not required @@ -257,7 +604,7 @@ void f() { - Can detect simple violations of this rule. It needs to examine each expression and make sure that no variable is modified twice in the expression. It also must check that no variable is modified once, then read elsewhere, with the single exception that a variable may appear on both the left and right of an assignment operator + Can detect simple violations of this rule. It needs to examine each expression and make sure that no variable is modified twice in the expression.ย It also mustย check thatย no variable is modified once, then read elsewhere, with the single exception that a variable may appear on both the left and right of an assignment operator
    - EVALUATION_ORDER + + EVALUATION_ORDER + Can detect the specific instance where a statement contains multiple side effects on the same value with an undefined evaluation order because, with different compiler flags or different compilers or platforms, the statement may behave differently @@ -286,7 +635,9 @@ void f() { 1.2 - CC2.EXP30 + + CC2.EXP30 + Fully implemented @@ -304,7 +655,9 @@ void f() { Can detect violations of this rule when the - -Wsequence-point + + -Wsequence-point + flag is used
    - C++3220, C++3221, C++3222, C++3223, C++3228 + + C++3220, C++3221, C++3222, C++3223, C++3228 + - PORTING.VAR.EFFECTS - MISRA.EXPR.PARENS - MISRA.EXPR.PARENS.INSUFFICIENT - MISRA.EXPR.PARENS.REDUNDANT - MISRA.INCR_DECR.OTHER + + + PORTING.VAR.EFFECTS + + + + + MISRA.EXPR.PARENS + + + + + MISRA.EXPR.PARENS.INSUFFICIENT + + + + + MISRA.EXPR.PARENS.REDUNDANT + + + + + MISRA.INCR_DECR.OTHER + + - 35 D - , 1 Q - , 9 S - , 134 S, 67 D, 72 D + + 35 D + + + , 1 Q + + + , 9 S + + + , 134 S, 67 D, 72 D + Partially implemented @@ -370,12 +753,24 @@ void f() { 2021.2 - CERT_CPP-EXP50-a - CERT_CPP-EXP50-b - CERT_CPP-EXP50-c - CERT_CPP-EXP50-d - CERT_CPP-EXP50-e - CERT_CPP-EXP50-f + + CERT_CPP-EXP50-a + + + CERT_CPP-EXP50-b + + + CERT_CPP-EXP50-c + + + CERT_CPP-EXP50-d + + + CERT_CPP-EXP50-e + + + CERT_CPP-EXP50-f + The value of an expression shall be the same under any order of evaluation that the standard permits @@ -414,7 +809,9 @@ void f() { 4.4 - 3220, 3221, 3222, 3223, 3228 + + 3220, 3221, 3222, 3223, 3228 + - 7.17 + 7.16 - V521 + + V521 + + + , - V708 + + + V708 + + - IncAndDecMixedWithOtherOperators + + + IncAndDecMixedWithOtherOperators + + Partially implemented @@ -469,7 +878,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType-standard.qhelp b/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType-standard.qhelp index dc793383a4..17a474ce5d 100644 --- a/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType-standard.qhelp +++ b/cpp/cert/src/rules/EXP51-CPP/DoNotDeleteAnArrayThroughAPointerOfTheIncorrectType-standard.qhelp @@ -1,15 +1,64 @@
    -

    The C++ Standard, [expr.delete], paragraph 3 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [expr.delete], paragraph 3ย [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

    +

    + In the first alternative ( + + delete object + + ), if the static type of the object to be deleted is different from itsย dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and theย static type shall have a virtual destructor or the behavior is undefined. In the second alternative ( + + deleteย array + + ) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined. +

    -

    Do not delete an array object through a static pointer type that differs from the dynamic pointer type of the object. Deleting an array through a pointer to the incorrect type results in undefined behavior.

    +

    + Do not delete an array object through a static pointer type that differs from the dynamic pointer type of the object. Deleting an array through a pointer to the incorrect type results in + + undefined behavior + + . +

    -

    In this noncompliant code example, an array of Derived objects is created and the pointer is stored in a Base *. Despite Base::~Base() being declared virtual, it still results in undefined behavior. Further, attempting to perform pointer arithmetic on the static type Base * violates CTR56-CPP. Do not use pointer arithmetic on polymorphic objects.

    - struct Base { +

    + In this noncompliant code example, an array of + + Derived + + objects is created and the pointer is stored in a + + Base * + + . Despite + + Base::~Base + + () being declared virtual, it still results in + + undefined behavior + + . Further, attempting to perform pointer arithmetic on the static type + + Base * + + violates + + CTR56-CPP. Do not use pointer arithmetic on polymorphic objects + + . +

    + + struct Base { virtual ~Base() = default; }; @@ -19,11 +68,27 @@ void f() { Base *b = new Derived[10]; // ... delete [] b; -} +} +
    -

    In this compliant solution, the static type of b is Derived *, which removes the undefined behavior when indexing into the array as well as when deleting the pointer.

    - struct Base { +

    + In this compliant solution, the static type of + + b + + is + + Derived * + + , which removes the + + undefined behavior + + when indexing into the array as well as when deleting the pointer. +

    + + struct Base { virtual ~Base() = default; }; @@ -33,10 +98,13 @@ void f() { Derived *b = new Derived[10]; // ... delete [] b; -} +} +
    -

    Attempting to destroy an array of polymorphic objects through the incorrect static type is undefined behavior. In practice, potential consequences include abnormal program execution and memory leaks.

    +

    + Attempting to destroy an array of polymorphic objects through the incorrect static type isย undefined behavior. In practice, potential consequences include abnormal program executionย and memory leaks. +

    @@ -73,10 +141,14 @@ void f() { Medium @@ -109,13 +181,19 @@ void f() { 3.9 @@ -128,7 +206,9 @@ void f() { 2021.2 @@ -143,7 +223,11 @@ void f() { 2021.4 @@ -158,7 +242,9 @@ void f() { 2021.2
    - P2 + + P2 + - L3 + + L3 +
    - -analyzer-checker=cplusplus + + -analyzer-checker=cplusplus + Checked with - clang -cc1 + + clang -cc1 + or (preferably) - scan-build + + scan-build +
    - C++3166 + + C++3166 + - CERT.EXPR.DELETE_ARR.BASE_PTR + + + CERT.EXPR.DELETE_ARR.BASE_PTR + + - CERT_CPP-EXP51-a + + CERT_CPP-EXP51-a + Do not treat arrays polymorphically @@ -182,7 +268,17 @@ void f() {
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand-standard.qhelp b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand-standard.qhelp index efc279dec8..258c817654 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand-standard.qhelp +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclTypeOperand-standard.qhelp @@ -1,64 +1,194 @@
    -

    Some expressions involve operands that are unevaluated. The C++ Standard, [expr], paragraph 8 [ISO/IEC 14882-2014] states the following:

    +

    + Some expressions involve operands that are + + unevaluated + + . The C++ Standard,ย [expr], paragraph 8 + [ + + ISO/IEC 14882-2014 + + ] states the following + : +

    -

    In some contexts, unevaluated operands appear. An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided. โ€” end note]

    +

    + In some contexts, + + unevaluated operands + + appear. An unevaluated operand is notย evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, aย non-static class member may be named (5.1) and naming of objects or functions does not, by itself, requireย that a definition be provided. โ€” end note] +

    -

    The following expressions do not evaluate their operands: sizeof(), typeid(), noexcept(), decltype(), and declval().

    -

    Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands.

    -

    Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function f() is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the sizeof() expression.

    - int f(int); +

    + The following expressions do not evaluate their operands: + + sizeof() + + , + + typeid() + + , + + noexcept() + + , + + decltype() + + , and + + declval() + + . +

    +

    + Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands. +

    +

    + Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function + + f() + + is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the + + sizeof() + + expression. +

    + + int f(int); double f(double); -size_t size = sizeof(f(0)); -

    Such a use does not rely on the side effects of f() and consequently conforms to this guideline.

    +size_t size = sizeof(f(0)); +
    +

    + Such a use does not rely on the side effects of + + f() + + and consequently conforms to this guideline. +

    -

    In this noncompliant code example, the expression a++ is not evaluated.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + a++ + + is not evaluated. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a++); std::cout << a << ", " << b << std::endl; -} -

    Consequently, the value of a after b has been initialized is 14.

    +} +
    +

    + Consequently, the value of + + a + + after + + b + + has been initialized is 14. +

    -

    In this compliant solution, the variable a is incremented outside of the sizeof operator.

    - #include <iostream> +

    + In this compliant solution, the variable + + a + + is incremented outside of the + + sizeof + + operator. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a); ++a; std::cout << a << ", " << b << std::endl; -} +} +
    -

    In this noncompliant code example, the expression i++ is not evaluated within the decltype specifier.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + i++ + + is not evaluated within the + + decltype + + specifier. +

    + + #include <iostream> void f() { int i = 0; decltype(i++) h = 12; std::cout << i; -} -

    Consequently, the value of i remains 0.

    +} +
    +

    + Consequently, the value of + i + remains 0. +

    -

    In this compliant solution, i is incremented outside of the decltype specifier so that it is evaluated as desired.

    - #include <iostream> +

    + In this compliant solution, + + i + + is incremented outside of the + + decltype + + specifier so that it is evaluated as desired. +

    + + #include <iostream> void f() { int i = 0; decltype(i) h = 12; ++i; std::cout << i; -} +} +
    -

    EXP52-CPP-EX1: It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or SFINAE context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects.

    -

    The following code is an example of compliant code using an unevaluated operand in a macro definition.

    - void small(int x); +

    + + EXP52-CPP-EX1: + + It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or + + SFINAE + + context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a macro definition. +

    + + void small(int x); void large(long long x); #define m(x) \ @@ -73,10 +203,36 @@ void large(long long x); void f() { int i = 0; m(++i); -} -

    The expansion of the macro m will result in the expression ++i being used as an unevaluated operand to sizeof(). However, the expectation of the programmer at the expansion loci is that i is preincremented only once. Consequently, this is a safe macro and complies with PRE31-C. Avoid side effects in arguments to unsafe macros. Compliance with that rule is especially important for code that follows this exception.

    -

    The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented.

    - #include <iostream> +} + +

    + The expansion of the macro + + m + + will result in the expression + + ++i + + being used as an unevaluated operand to + + sizeof() + + . However, the expectation of the programmer at the expansion loci is that + + i + + is preincremented only once. Consequently, this is a safe macro and complies with + + PRE31-C. Avoid side effects in arguments to unsafe macros + + . Compliance with that rule is especially important for code that follows this exception. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented. +

    + + #include <iostream> #include <type_traits> #include <utility> @@ -93,11 +249,20 @@ public: void f() { std::cout << std::boolalpha << is_incrementable<int>::value; -} -

    In an instantiation of is_incrementable, the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE.

    +} +
    +

    + In an instantiation of + + is_incrementable + + , the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE. +

    -

    If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.

    +

    + If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior. +

    @@ -134,10 +299,14 @@ void f() { Low @@ -170,7 +339,9 @@ void f() { 20.10 @@ -201,7 +374,9 @@ void f() { 3.9 @@ -216,7 +391,9 @@ void f() { 2021.2 @@ -231,7 +408,11 @@ void f() { 2021.4 @@ -245,7 +426,9 @@ void f() { @@ -316,7 +509,9 @@ void f() { 20.10
    - P3 + + P3 + - L3 + + L3 +
    - sizeof + + sizeof + Partially checked @@ -186,7 +357,9 @@ void f() { 7.2.0 - CertC++-EXP52 + + CertC++-EXP52 + - -Wunevaluated-expression + + -Wunevaluated-expression + - C++3240, C++3241 + + C++3240, C++3241 + - MISRA.SIZEOF.SIDE_EFFECT + + + MISRA.SIZEOF.SIDE_EFFECT + + - 54 S, 133 S + + 54 S, 133 S + Partially implemented @@ -261,9 +444,17 @@ void f() { 2021.2 - CERT_CPP-EXP52-a - CERT_CPP-EXP52-b - CERT_CPP-EXP52-cCERT_CPP-EXP52-dCERT_CPP-EXP52-e + + CERT_CPP-EXP52-a + + + CERT_CPP-EXP52-b + + + CERT_CPP-EXP52-c + CERT_CPP-EXP52-d + CERT_CPP-EXP52-e + The operand of the sizeof operator shall not contain any expression which has side effects @@ -301,7 +492,9 @@ void f() { 4.4 - 3240, 3241 + + 3240, 3241 + - sizeof + + sizeof + Partially checked @@ -326,7 +521,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -360,7 +565,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression-standard.qhelp b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression-standard.qhelp index efc279dec8..258c817654 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression-standard.qhelp +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInDeclValExpression-standard.qhelp @@ -1,64 +1,194 @@
    -

    Some expressions involve operands that are unevaluated. The C++ Standard, [expr], paragraph 8 [ISO/IEC 14882-2014] states the following:

    +

    + Some expressions involve operands that are + + unevaluated + + . The C++ Standard,ย [expr], paragraph 8 + [ + + ISO/IEC 14882-2014 + + ] states the following + : +

    -

    In some contexts, unevaluated operands appear. An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided. โ€” end note]

    +

    + In some contexts, + + unevaluated operands + + appear. An unevaluated operand is notย evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, aย non-static class member may be named (5.1) and naming of objects or functions does not, by itself, requireย that a definition be provided. โ€” end note] +

    -

    The following expressions do not evaluate their operands: sizeof(), typeid(), noexcept(), decltype(), and declval().

    -

    Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands.

    -

    Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function f() is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the sizeof() expression.

    - int f(int); +

    + The following expressions do not evaluate their operands: + + sizeof() + + , + + typeid() + + , + + noexcept() + + , + + decltype() + + , and + + declval() + + . +

    +

    + Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands. +

    +

    + Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function + + f() + + is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the + + sizeof() + + expression. +

    + + int f(int); double f(double); -size_t size = sizeof(f(0)); -

    Such a use does not rely on the side effects of f() and consequently conforms to this guideline.

    +size_t size = sizeof(f(0)); +
    +

    + Such a use does not rely on the side effects of + + f() + + and consequently conforms to this guideline. +

    -

    In this noncompliant code example, the expression a++ is not evaluated.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + a++ + + is not evaluated. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a++); std::cout << a << ", " << b << std::endl; -} -

    Consequently, the value of a after b has been initialized is 14.

    +} +
    +

    + Consequently, the value of + + a + + after + + b + + has been initialized is 14. +

    -

    In this compliant solution, the variable a is incremented outside of the sizeof operator.

    - #include <iostream> +

    + In this compliant solution, the variable + + a + + is incremented outside of the + + sizeof + + operator. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a); ++a; std::cout << a << ", " << b << std::endl; -} +} +
    -

    In this noncompliant code example, the expression i++ is not evaluated within the decltype specifier.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + i++ + + is not evaluated within the + + decltype + + specifier. +

    + + #include <iostream> void f() { int i = 0; decltype(i++) h = 12; std::cout << i; -} -

    Consequently, the value of i remains 0.

    +} +
    +

    + Consequently, the value of + i + remains 0. +

    -

    In this compliant solution, i is incremented outside of the decltype specifier so that it is evaluated as desired.

    - #include <iostream> +

    + In this compliant solution, + + i + + is incremented outside of the + + decltype + + specifier so that it is evaluated as desired. +

    + + #include <iostream> void f() { int i = 0; decltype(i) h = 12; ++i; std::cout << i; -} +} +
    -

    EXP52-CPP-EX1: It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or SFINAE context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects.

    -

    The following code is an example of compliant code using an unevaluated operand in a macro definition.

    - void small(int x); +

    + + EXP52-CPP-EX1: + + It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or + + SFINAE + + context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a macro definition. +

    + + void small(int x); void large(long long x); #define m(x) \ @@ -73,10 +203,36 @@ void large(long long x); void f() { int i = 0; m(++i); -} -

    The expansion of the macro m will result in the expression ++i being used as an unevaluated operand to sizeof(). However, the expectation of the programmer at the expansion loci is that i is preincremented only once. Consequently, this is a safe macro and complies with PRE31-C. Avoid side effects in arguments to unsafe macros. Compliance with that rule is especially important for code that follows this exception.

    -

    The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented.

    - #include <iostream> +} + +

    + The expansion of the macro + + m + + will result in the expression + + ++i + + being used as an unevaluated operand to + + sizeof() + + . However, the expectation of the programmer at the expansion loci is that + + i + + is preincremented only once. Consequently, this is a safe macro and complies with + + PRE31-C. Avoid side effects in arguments to unsafe macros + + . Compliance with that rule is especially important for code that follows this exception. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented. +

    + + #include <iostream> #include <type_traits> #include <utility> @@ -93,11 +249,20 @@ public: void f() { std::cout << std::boolalpha << is_incrementable<int>::value; -} -

    In an instantiation of is_incrementable, the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE.

    +} +
    +

    + In an instantiation of + + is_incrementable + + , the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE. +

    -

    If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.

    +

    + If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior. +

    Clause 5, "Expressions" Subclause 20.2.5, "Function Template - declval + + declval + "
    @@ -134,10 +299,14 @@ void f() { Low @@ -170,7 +339,9 @@ void f() { 20.10 @@ -201,7 +374,9 @@ void f() { 3.9 @@ -216,7 +391,9 @@ void f() { 2021.2 @@ -231,7 +408,11 @@ void f() { 2021.4 @@ -245,7 +426,9 @@ void f() { @@ -316,7 +509,9 @@ void f() { 20.10
    - P3 + + P3 + - L3 + + L3 +
    - sizeof + + sizeof + Partially checked @@ -186,7 +357,9 @@ void f() { 7.2.0 - CertC++-EXP52 + + CertC++-EXP52 + - -Wunevaluated-expression + + -Wunevaluated-expression + - C++3240, C++3241 + + C++3240, C++3241 + - MISRA.SIZEOF.SIDE_EFFECT + + + MISRA.SIZEOF.SIDE_EFFECT + + - 54 S, 133 S + + 54 S, 133 S + Partially implemented @@ -261,9 +444,17 @@ void f() { 2021.2 - CERT_CPP-EXP52-a - CERT_CPP-EXP52-b - CERT_CPP-EXP52-cCERT_CPP-EXP52-dCERT_CPP-EXP52-e + + CERT_CPP-EXP52-a + + + CERT_CPP-EXP52-b + + + CERT_CPP-EXP52-c + CERT_CPP-EXP52-d + CERT_CPP-EXP52-e + The operand of the sizeof operator shall not contain any expression which has side effects @@ -301,7 +492,9 @@ void f() { 4.4 - 3240, 3241 + + 3240, 3241 + - sizeof + + sizeof + Partially checked @@ -326,7 +521,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -360,7 +565,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand-standard.qhelp b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand-standard.qhelp index efc279dec8..258c817654 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand-standard.qhelp +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInNoExceptOperand-standard.qhelp @@ -1,64 +1,194 @@
    -

    Some expressions involve operands that are unevaluated. The C++ Standard, [expr], paragraph 8 [ISO/IEC 14882-2014] states the following:

    +

    + Some expressions involve operands that are + + unevaluated + + . The C++ Standard,ย [expr], paragraph 8 + [ + + ISO/IEC 14882-2014 + + ] states the following + : +

    -

    In some contexts, unevaluated operands appear. An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided. โ€” end note]

    +

    + In some contexts, + + unevaluated operands + + appear. An unevaluated operand is notย evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, aย non-static class member may be named (5.1) and naming of objects or functions does not, by itself, requireย that a definition be provided. โ€” end note] +

    -

    The following expressions do not evaluate their operands: sizeof(), typeid(), noexcept(), decltype(), and declval().

    -

    Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands.

    -

    Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function f() is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the sizeof() expression.

    - int f(int); +

    + The following expressions do not evaluate their operands: + + sizeof() + + , + + typeid() + + , + + noexcept() + + , + + decltype() + + , and + + declval() + + . +

    +

    + Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands. +

    +

    + Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function + + f() + + is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the + + sizeof() + + expression. +

    + + int f(int); double f(double); -size_t size = sizeof(f(0)); -

    Such a use does not rely on the side effects of f() and consequently conforms to this guideline.

    +size_t size = sizeof(f(0)); +
    +

    + Such a use does not rely on the side effects of + + f() + + and consequently conforms to this guideline. +

    -

    In this noncompliant code example, the expression a++ is not evaluated.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + a++ + + is not evaluated. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a++); std::cout << a << ", " << b << std::endl; -} -

    Consequently, the value of a after b has been initialized is 14.

    +} +
    +

    + Consequently, the value of + + a + + after + + b + + has been initialized is 14. +

    -

    In this compliant solution, the variable a is incremented outside of the sizeof operator.

    - #include <iostream> +

    + In this compliant solution, the variable + + a + + is incremented outside of the + + sizeof + + operator. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a); ++a; std::cout << a << ", " << b << std::endl; -} +} +
    -

    In this noncompliant code example, the expression i++ is not evaluated within the decltype specifier.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + i++ + + is not evaluated within the + + decltype + + specifier. +

    + + #include <iostream> void f() { int i = 0; decltype(i++) h = 12; std::cout << i; -} -

    Consequently, the value of i remains 0.

    +} +
    +

    + Consequently, the value of + i + remains 0. +

    -

    In this compliant solution, i is incremented outside of the decltype specifier so that it is evaluated as desired.

    - #include <iostream> +

    + In this compliant solution, + + i + + is incremented outside of the + + decltype + + specifier so that it is evaluated as desired. +

    + + #include <iostream> void f() { int i = 0; decltype(i) h = 12; ++i; std::cout << i; -} +} +
    -

    EXP52-CPP-EX1: It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or SFINAE context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects.

    -

    The following code is an example of compliant code using an unevaluated operand in a macro definition.

    - void small(int x); +

    + + EXP52-CPP-EX1: + + It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or + + SFINAE + + context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a macro definition. +

    + + void small(int x); void large(long long x); #define m(x) \ @@ -73,10 +203,36 @@ void large(long long x); void f() { int i = 0; m(++i); -} -

    The expansion of the macro m will result in the expression ++i being used as an unevaluated operand to sizeof(). However, the expectation of the programmer at the expansion loci is that i is preincremented only once. Consequently, this is a safe macro and complies with PRE31-C. Avoid side effects in arguments to unsafe macros. Compliance with that rule is especially important for code that follows this exception.

    -

    The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented.

    - #include <iostream> +} + +

    + The expansion of the macro + + m + + will result in the expression + + ++i + + being used as an unevaluated operand to + + sizeof() + + . However, the expectation of the programmer at the expansion loci is that + + i + + is preincremented only once. Consequently, this is a safe macro and complies with + + PRE31-C. Avoid side effects in arguments to unsafe macros + + . Compliance with that rule is especially important for code that follows this exception. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented. +

    + + #include <iostream> #include <type_traits> #include <utility> @@ -93,11 +249,20 @@ public: void f() { std::cout << std::boolalpha << is_incrementable<int>::value; -} -

    In an instantiation of is_incrementable, the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE.

    +} +
    +

    + In an instantiation of + + is_incrementable + + , the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE. +

    -

    If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.

    +

    + If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior. +

    Clause 5, "Expressions" Subclause 20.2.5, "Function Template - declval + + declval + "
    @@ -134,10 +299,14 @@ void f() { Low @@ -170,7 +339,9 @@ void f() { 20.10 @@ -201,7 +374,9 @@ void f() { 3.9 @@ -216,7 +391,9 @@ void f() { 2021.2 @@ -231,7 +408,11 @@ void f() { 2021.4 @@ -245,7 +426,9 @@ void f() { @@ -316,7 +509,9 @@ void f() { 20.10
    - P3 + + P3 + - L3 + + L3 +
    - sizeof + + sizeof + Partially checked @@ -186,7 +357,9 @@ void f() { 7.2.0 - CertC++-EXP52 + + CertC++-EXP52 + - -Wunevaluated-expression + + -Wunevaluated-expression + - C++3240, C++3241 + + C++3240, C++3241 + - MISRA.SIZEOF.SIDE_EFFECT + + + MISRA.SIZEOF.SIDE_EFFECT + + - 54 S, 133 S + + 54 S, 133 S + Partially implemented @@ -261,9 +444,17 @@ void f() { 2021.2 - CERT_CPP-EXP52-a - CERT_CPP-EXP52-b - CERT_CPP-EXP52-cCERT_CPP-EXP52-dCERT_CPP-EXP52-e + + CERT_CPP-EXP52-a + + + CERT_CPP-EXP52-b + + + CERT_CPP-EXP52-c + CERT_CPP-EXP52-d + CERT_CPP-EXP52-e + The operand of the sizeof operator shall not contain any expression which has side effects @@ -301,7 +492,9 @@ void f() { 4.4 - 3240, 3241 + + 3240, 3241 + - sizeof + + sizeof + Partially checked @@ -326,7 +521,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -360,7 +565,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand-standard.qhelp b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand-standard.qhelp index efc279dec8..258c817654 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand-standard.qhelp +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInSizeOfOperand-standard.qhelp @@ -1,64 +1,194 @@
    -

    Some expressions involve operands that are unevaluated. The C++ Standard, [expr], paragraph 8 [ISO/IEC 14882-2014] states the following:

    +

    + Some expressions involve operands that are + + unevaluated + + . The C++ Standard,ย [expr], paragraph 8 + [ + + ISO/IEC 14882-2014 + + ] states the following + : +

    -

    In some contexts, unevaluated operands appear. An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided. โ€” end note]

    +

    + In some contexts, + + unevaluated operands + + appear. An unevaluated operand is notย evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, aย non-static class member may be named (5.1) and naming of objects or functions does not, by itself, requireย that a definition be provided. โ€” end note] +

    -

    The following expressions do not evaluate their operands: sizeof(), typeid(), noexcept(), decltype(), and declval().

    -

    Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands.

    -

    Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function f() is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the sizeof() expression.

    - int f(int); +

    + The following expressions do not evaluate their operands: + + sizeof() + + , + + typeid() + + , + + noexcept() + + , + + decltype() + + , and + + declval() + + . +

    +

    + Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands. +

    +

    + Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function + + f() + + is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the + + sizeof() + + expression. +

    + + int f(int); double f(double); -size_t size = sizeof(f(0)); -

    Such a use does not rely on the side effects of f() and consequently conforms to this guideline.

    +size_t size = sizeof(f(0)); +
    +

    + Such a use does not rely on the side effects of + + f() + + and consequently conforms to this guideline. +

    -

    In this noncompliant code example, the expression a++ is not evaluated.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + a++ + + is not evaluated. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a++); std::cout << a << ", " << b << std::endl; -} -

    Consequently, the value of a after b has been initialized is 14.

    +} +
    +

    + Consequently, the value of + + a + + after + + b + + has been initialized is 14. +

    -

    In this compliant solution, the variable a is incremented outside of the sizeof operator.

    - #include <iostream> +

    + In this compliant solution, the variable + + a + + is incremented outside of the + + sizeof + + operator. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a); ++a; std::cout << a << ", " << b << std::endl; -} +} +
    -

    In this noncompliant code example, the expression i++ is not evaluated within the decltype specifier.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + i++ + + is not evaluated within the + + decltype + + specifier. +

    + + #include <iostream> void f() { int i = 0; decltype(i++) h = 12; std::cout << i; -} -

    Consequently, the value of i remains 0.

    +} +
    +

    + Consequently, the value of + i + remains 0. +

    -

    In this compliant solution, i is incremented outside of the decltype specifier so that it is evaluated as desired.

    - #include <iostream> +

    + In this compliant solution, + + i + + is incremented outside of the + + decltype + + specifier so that it is evaluated as desired. +

    + + #include <iostream> void f() { int i = 0; decltype(i) h = 12; ++i; std::cout << i; -} +} +
    -

    EXP52-CPP-EX1: It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or SFINAE context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects.

    -

    The following code is an example of compliant code using an unevaluated operand in a macro definition.

    - void small(int x); +

    + + EXP52-CPP-EX1: + + It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or + + SFINAE + + context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a macro definition. +

    + + void small(int x); void large(long long x); #define m(x) \ @@ -73,10 +203,36 @@ void large(long long x); void f() { int i = 0; m(++i); -} -

    The expansion of the macro m will result in the expression ++i being used as an unevaluated operand to sizeof(). However, the expectation of the programmer at the expansion loci is that i is preincremented only once. Consequently, this is a safe macro and complies with PRE31-C. Avoid side effects in arguments to unsafe macros. Compliance with that rule is especially important for code that follows this exception.

    -

    The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented.

    - #include <iostream> +} + +

    + The expansion of the macro + + m + + will result in the expression + + ++i + + being used as an unevaluated operand to + + sizeof() + + . However, the expectation of the programmer at the expansion loci is that + + i + + is preincremented only once. Consequently, this is a safe macro and complies with + + PRE31-C. Avoid side effects in arguments to unsafe macros + + . Compliance with that rule is especially important for code that follows this exception. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented. +

    + + #include <iostream> #include <type_traits> #include <utility> @@ -93,11 +249,20 @@ public: void f() { std::cout << std::boolalpha << is_incrementable<int>::value; -} -

    In an instantiation of is_incrementable, the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE.

    +} +
    +

    + In an instantiation of + + is_incrementable + + , the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE. +

    -

    If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.

    +

    + If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior. +

    Clause 5, "Expressions" Subclause 20.2.5, "Function Template - declval + + declval + "
    @@ -134,10 +299,14 @@ void f() { Low @@ -170,7 +339,9 @@ void f() { 20.10 @@ -201,7 +374,9 @@ void f() { 3.9 @@ -216,7 +391,9 @@ void f() { 2021.2 @@ -231,7 +408,11 @@ void f() { 2021.4 @@ -245,7 +426,9 @@ void f() { @@ -316,7 +509,9 @@ void f() { 20.10
    - P3 + + P3 + - L3 + + L3 +
    - sizeof + + sizeof + Partially checked @@ -186,7 +357,9 @@ void f() { 7.2.0 - CertC++-EXP52 + + CertC++-EXP52 + - -Wunevaluated-expression + + -Wunevaluated-expression + - C++3240, C++3241 + + C++3240, C++3241 + - MISRA.SIZEOF.SIDE_EFFECT + + + MISRA.SIZEOF.SIDE_EFFECT + + - 54 S, 133 S + + 54 S, 133 S + Partially implemented @@ -261,9 +444,17 @@ void f() { 2021.2 - CERT_CPP-EXP52-a - CERT_CPP-EXP52-b - CERT_CPP-EXP52-cCERT_CPP-EXP52-dCERT_CPP-EXP52-e + + CERT_CPP-EXP52-a + + + CERT_CPP-EXP52-b + + + CERT_CPP-EXP52-c + CERT_CPP-EXP52-d + CERT_CPP-EXP52-e + The operand of the sizeof operator shall not contain any expression which has side effects @@ -301,7 +492,9 @@ void f() { 4.4 - 3240, 3241 + + 3240, 3241 + - sizeof + + sizeof + Partially checked @@ -326,7 +521,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -360,7 +565,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand-standard.qhelp b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand-standard.qhelp index efc279dec8..258c817654 100644 --- a/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand-standard.qhelp +++ b/cpp/cert/src/rules/EXP52-CPP/DoNotRelyOnSideEffectsInTypeIdOperand-standard.qhelp @@ -1,64 +1,194 @@
    -

    Some expressions involve operands that are unevaluated. The C++ Standard, [expr], paragraph 8 [ISO/IEC 14882-2014] states the following:

    +

    + Some expressions involve operands that are + + unevaluated + + . The C++ Standard,ย [expr], paragraph 8 + [ + + ISO/IEC 14882-2014 + + ] states the following + : +

    -

    In some contexts, unevaluated operands appear. An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided. โ€” end note]

    +

    + In some contexts, + + unevaluated operands + + appear. An unevaluated operand is notย evaluated. An unevaluated operand is considered a full-expression. [Note: In an unevaluated operand, aย non-static class member may be named (5.1) and naming of objects or functions does not, by itself, requireย that a definition be provided. โ€” end note] +

    -

    The following expressions do not evaluate their operands: sizeof(), typeid(), noexcept(), decltype(), and declval().

    -

    Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands.

    -

    Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function f() is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the sizeof() expression.

    - int f(int); +

    + The following expressions do not evaluate their operands: + + sizeof() + + , + + typeid() + + , + + noexcept() + + , + + decltype() + + , and + + declval() + + . +

    +

    + Because an unevaluated operand in an expression is not evaluated, no side effects from that operand are triggered. Reliance on those side effects will result in unexpected behavior. Do not rely on side effects in unevaluated operands. +

    +

    + Unevaluated expression operands are used when the declaration of an object is required but the definition of the object is not. For instance, in the following example, the function + + f() + + is overloaded, relying on the unevaluated expression operand to select the desired overload, which is then used to determine the result of the + + sizeof() + + expression. +

    + + int f(int); double f(double); -size_t size = sizeof(f(0)); -

    Such a use does not rely on the side effects of f() and consequently conforms to this guideline.

    +size_t size = sizeof(f(0)); +
    +

    + Such a use does not rely on the side effects of + + f() + + and consequently conforms to this guideline. +

    -

    In this noncompliant code example, the expression a++ is not evaluated.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + a++ + + is not evaluated. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a++); std::cout << a << ", " << b << std::endl; -} -

    Consequently, the value of a after b has been initialized is 14.

    +} +
    +

    + Consequently, the value of + + a + + after + + b + + has been initialized is 14. +

    -

    In this compliant solution, the variable a is incremented outside of the sizeof operator.

    - #include <iostream> +

    + In this compliant solution, the variable + + a + + is incremented outside of the + + sizeof + + operator. +

    + + #include <iostream> void f() { int a = 14; int b = sizeof(a); ++a; std::cout << a << ", " << b << std::endl; -} +} +
    -

    In this noncompliant code example, the expression i++ is not evaluated within the decltype specifier.

    - #include <iostream> +

    + In this noncompliant code example, the expression + + i++ + + is not evaluated within the + + decltype + + specifier. +

    + + #include <iostream> void f() { int i = 0; decltype(i++) h = 12; std::cout << i; -} -

    Consequently, the value of i remains 0.

    +} +
    +

    + Consequently, the value of + i + remains 0. +

    -

    In this compliant solution, i is incremented outside of the decltype specifier so that it is evaluated as desired.

    - #include <iostream> +

    + In this compliant solution, + + i + + is incremented outside of the + + decltype + + specifier so that it is evaluated as desired. +

    + + #include <iostream> void f() { int i = 0; decltype(i) h = 12; ++i; std::cout << i; -} +} +
    -

    EXP52-CPP-EX1: It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or SFINAE context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects.

    -

    The following code is an example of compliant code using an unevaluated operand in a macro definition.

    - void small(int x); +

    + + EXP52-CPP-EX1: + + It is permissible for an expression with side effects to be used as an unevaluated operand in a macro definition or + + SFINAE + + context. Although these situations rely on the side effects to produce valid code, they typically do not rely on values produced as a result of the side effects. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a macro definition. +

    + + void small(int x); void large(long long x); #define m(x) \ @@ -73,10 +203,36 @@ void large(long long x); void f() { int i = 0; m(++i); -} -

    The expansion of the macro m will result in the expression ++i being used as an unevaluated operand to sizeof(). However, the expectation of the programmer at the expansion loci is that i is preincremented only once. Consequently, this is a safe macro and complies with PRE31-C. Avoid side effects in arguments to unsafe macros. Compliance with that rule is especially important for code that follows this exception.

    -

    The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented.

    - #include <iostream> +} + +

    + The expansion of the macro + + m + + will result in the expression + + ++i + + being used as an unevaluated operand to + + sizeof() + + . However, the expectation of the programmer at the expansion loci is that + + i + + is preincremented only once. Consequently, this is a safe macro and complies with + + PRE31-C. Avoid side effects in arguments to unsafe macros + + . Compliance with that rule is especially important for code that follows this exception. +

    +

    + The following code is an example of compliant code using an unevaluated operand in a SFINAE context to determine whether a type can be postfix incremented. +

    + + #include <iostream> #include <type_traits> #include <utility> @@ -93,11 +249,20 @@ public: void f() { std::cout << std::boolalpha << is_incrementable<int>::value; -} -

    In an instantiation of is_incrementable, the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE.

    +} +
    +

    + In an instantiation of + + is_incrementable + + , the use of the postfix increment operator generates side effects that are used to determine whether the type is postfix incrementable. However, the value result of these side effects is discarded, so the side effects are used only for SFINAE. +

    -

    If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior.

    +

    + If expressions that appear to produce side effects are an unevaluated operand, the results may be different than expected. Depending on how this result is used, it can lead to unintended program behavior. +

    Clause 5, "Expressions" Subclause 20.2.5, "Function Template - declval + + declval + "
    @@ -134,10 +299,14 @@ void f() { Low @@ -170,7 +339,9 @@ void f() { 20.10 @@ -201,7 +374,9 @@ void f() { 3.9 @@ -216,7 +391,9 @@ void f() { 2021.2 @@ -231,7 +408,11 @@ void f() { 2021.4 @@ -245,7 +426,9 @@ void f() { @@ -316,7 +509,9 @@ void f() { 20.10
    - P3 + + P3 + - L3 + + L3 +
    - sizeof + + sizeof + Partially checked @@ -186,7 +357,9 @@ void f() { 7.2.0 - CertC++-EXP52 + + CertC++-EXP52 + - -Wunevaluated-expression + + -Wunevaluated-expression + - C++3240, C++3241 + + C++3240, C++3241 + - MISRA.SIZEOF.SIDE_EFFECT + + + MISRA.SIZEOF.SIDE_EFFECT + + - 54 S, 133 S + + 54 S, 133 S + Partially implemented @@ -261,9 +444,17 @@ void f() { 2021.2 - CERT_CPP-EXP52-a - CERT_CPP-EXP52-b - CERT_CPP-EXP52-cCERT_CPP-EXP52-dCERT_CPP-EXP52-e + + CERT_CPP-EXP52-a + + + CERT_CPP-EXP52-b + + + CERT_CPP-EXP52-c + CERT_CPP-EXP52-d + CERT_CPP-EXP52-e + The operand of the sizeof operator shall not contain any expression which has side effects @@ -301,7 +492,9 @@ void f() { 4.4 - 3240, 3241 + + 3240, 3241 + - sizeof + + sizeof + Partially checked @@ -326,7 +521,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -360,7 +565,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory-standard.qhelp b/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory-standard.qhelp index 517fad3973..cd071cc8bd 100644 --- a/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory-standard.qhelp +++ b/cpp/cert/src/rules/EXP53-CPP/DoNotReadUninitializedMemory-standard.qhelp @@ -1,78 +1,292 @@
    -

    Local, automatic variables assume unexpected values if they are read before they are initialized. The C++ Standard, [dcl.init], paragraph 12 [ISO/IEC 14882-2014], states the following:

    +

    + Local, automatic variables assume unexpected values if they are read before they are initialized. The C++ Standard, [dcl.init], paragraph 12 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced. If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:

    -

    โ€” If an indeterminate value of unsigned narrow character type is produced by the evaluation of: โ€” the second or third operand of a conditional expression, โ€” the right operand of a comma expression, โ€” the operand of a cast or conversion to an unsigned narrow character type, or โ€” a discarded-value expression,then the result of the operation is an indeterminate value.โ€” If an indeterminate value of unsigned narrow character type is produced by the evaluation of the right operand of a simple assignment operator whose first operand is an lvalue of unsigned narrow character type, an indeterminate value replaces the value of the object referred to by the left operand.โ€” If an indeterminate value of unsigned narrow character type is produced by the evaluation of the initialization expression when initializing an object of unsigned narrow character type, that object is initialized to an indeterminate value.

    +

    + If no initializer is specified for an object, the object is default-initialized. When storage for an objectย with automatic or dynamic storage duration is obtained, the object has an + + indeterminate value + + , and ifย no initialization is performed for the object, that object retains an indeterminate value until that value isย replaced.ย If an indeterminate value is produced by an evaluation, the behavior is undefined except in theย following cases: +

    +

    + โ€” If an indeterminate value of unsigned narrow character type is produced by the evaluation of: + โ€” the second or third operand of a conditional expression, + โ€” the right operand of a comma expression, + โ€” the operand of a cast or conversion to an unsigned narrow character type,ย or + โ€” a discarded-value expression, + then the result of the operation is an indeterminate value. + โ€” If an indeterminate value of unsigned narrow character type is produced by the evaluation of the rightย operand of a simple assignment operator whose first operand is an lvalue of unsigned narrowย character type, an indeterminate value replaces the value of the object referred to by the left operand. + โ€” If an indeterminate value of unsigned narrow character type is produced by the evaluation of theย initialization expression when initializing an object of unsigned narrow character type, that object isย initialized to an indeterminate value. +

    -

    The default initialization of an object is described by paragraph 7 of the same subclause:

    +

    + The default initialization of an object is described by paragraph 7 of the same subclause: +

    -

    To default-initialize an object of type T means:โ€” if T is a (possibly cv-qualified) class type, the default constructor for T is called (and the initialization is ill-formed if T has no default constructor or overload resolution results in an ambiguity or in a function that is deleted or inaccessible from the context of the initialization);โ€” if T is an array type, each element is default-initialized;โ€” otherwise, no initialization is performed.If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

    +

    + To + + default-initialize + + an object of type + + T + + means: + โ€” if + + T + + is a (possibly cv-qualified) class type, the default constructor for + + T + + is called (andย the initialization is ill-formed if + + T + + has no default constructor or overload resolution results in anย ambiguity or in a function that is deleted or inaccessible from the context of the initialization); + โ€” if + + T + + is an array type, each element is default-initialized; + โ€” otherwise, no initialization is performed. + If a program calls for the default initialization of an object of a const-qualified type + + T + + , + + T + + shall be a classย type with a user-provided default constructor. +

    -

    As a result, objects of type T with automatic or dynamic storage duration must be explicitly initialized before having their value read as part of an expression unless T is a class type or an array thereof or is an unsigned narrow character type. If T is an unsigned narrow character type, it may be used to initialize an object of unsigned narrow character type, which results in both objects having an indeterminate value. This technique can be used to implement copy operations such as std::memcpy() without triggering undefined behavior.

    -

    Additionally, memory dynamically allocated with a new expression is default-initialized when the new-initialized is omitted. Memory allocated by the standard library function std::calloc() is zero-initialized. Memory allocated by the standard library function std::realloc() assumes the values of the original pointer but may not initialize the full range of memory. Memory allocated by any other means ( std::malloc(), allocator objects, operator new(), and so on) is assumed to be default-initialized.

    -

    Objects of static or thread storage duration are zero-initialized before any other initialization takes place [ISO/IEC 14882-2014] and need not be explicitly initialized before having their value read.

    -

    Reading uninitialized variables for creating entropy is problematic because these memory accesses can be removed by compiler optimization. VU925211 is an example of a vulnerability caused by this coding error [VU#925211].

    +

    + As a result, objects of type + + T + + with automatic or dynamic storage duration must be explicitly initialized before having their value read as part of an expression unless + + T + + is a class type or an array thereof or is an unsigned narrow character type. If + + T + + is an unsigned narrow character type, it may be used to initialize an object of unsigned narrow character type, which results in both objects having an + + indeterminate value + + . This technique can be used to implement copy operations such as + + std::memcpy() + + without triggering + + undefined behavior + + . +

    +

    + Additionally, memory + dynamically allocated with a + + new + + expression is default-initialized when the + + new-initialized + + is omitted. Memory allocated by the standard library function + + std::calloc() + + is zero-initialized. Memory allocated by the standard library function + + std::realloc() + + assumes the values of the original pointer but may not initialize the full range of memory. Memory allocated by any other means ( + + std::malloc() + + , allocator objects, + + operator new() + + , and so on) is assumed to be default-initialized. +

    +

    + Objects of static or thread storage duration are zero-initialized before any other initialization takes place [ + + ISO/IEC 14882-2014 + + ] and need not be explicitly initialized before having their value read. +

    +

    + Reading uninitialized variables for creating entropy is problematic because these memory accesses can be removed by compiler optimization. + VU925211 + is an example of a + + vulnerability + + caused by this coding error [ + + VU#925211 + + ]. +

    -

    In this noncompliant code example, an uninitialized local variable is evaluated as part of an expression to print its value, resulting in undefined behavior.

    - #include <iostream> - +

    + In this noncompliant code example, an uninitialized local variable is evaluated as part of an expression to print its value, resulting in + + undefined behavior + + . +

    + + #include <iostream> +ย  void f() { int i; std::cout << i; -} +} +
    -

    In this compliant solution, the object is initialized prior to printing its value.

    - #include <iostream> - +

    + In this compliant solution, the object is initialized prior to printing its value. +

    + + #include <iostream> +ย  void f() { int i = 0; std::cout << i; -} +} +
    -

    In this noncompliant code example, an int * object is allocated by a new-expression, but the memory it points to is not initialized. The object's pointer value and the value it points to are printed to the standard output stream. Printing the pointer value is well-defined, but attempting to print the value pointed to yields an indeterminate value, resulting in undefined behavior.

    - #include <iostream> - +

    + In this noncompliant code example, an + + int * + + object is allocated by a + + new-expression + + , but the memory it points to is not initialized. The object's pointer value and the value it points to are printed to the standard output stream. Printing the pointer value is well-defined, but attempting to print the value pointed to yields an + + indeterminate value + + , resulting in + + undefined behavior + + . +

    + + #include <iostream> +ย  void f() { int *i = new int; std::cout << i << ", " << *i; -} +} +
    -

    In this compliant solution, the memory is direct-initialized to the value 12 prior to printing its value.

    - #include <iostream> +

    + In this compliant solution, the memory is direct-initialized to the value + + 12 + + prior to printing its value. +

    + + #include <iostream> void f() { int *i = new int(12); std::cout << i << ", " << *i; -} -

    Initialization of an object produced by a new-expression is performed by placing (possibly empty) parenthesis or curly braces after the type being allocated. This causes direct initialization of the pointed-to object to occur, which will zero-initialize the object if the initialization omits a value, as illustrated by the following code.

    - int *i = new int(); // zero-initializes *i +} + +

    + Initialization of an object produced by a + + new-expression + + is performed by placing (possibly empty) parenthesis or curly braces after the type being allocated. This causes direct initialization of the pointed-to object to occur, which will zero-initialize the object if the initialization omits a value, as illustrated by the following code. +

    + + int *i = new int(); // zero-initializes *i int *j = new int{}; // zero-initializes *j int *k = new int(12); // initializes *k to 12 -int *l = new int{12}; // initializes *l to 12 +int *l = new int{12}; // initializes *l to 12 +
    -

    In this noncompliant code example, the class member variable c is not explicitly initialized by a ctor-initializer in the default constructor. Despite the local variable s being default-initialized, the use of c within the call to S::f() results in the evaluation of an object with indeterminate value, resulting in undefined behavior.

    - class S { +

    + In this noncompliant code example, the class member variable + + c + + is not explicitly initialized by a + + ctor-initializer + + in the default constructor. Despite the local variable + + s + + being default-initialized, the use of + + c + + within the call to + + S::f() + + results in the evaluation of an object with indeterminate value, resulting in undefined behavior. +

    + + class S { int c; - +ย  public: int f(int i) const { return i + c; } }; - +ย  void f() { S s; int i = s.f(10); -} +} +
    -

    In this compliant solution, S is given a default constructor that initializes the class member variable c.

    - class S { +

    + In this compliant solution, + + S + + is given a default constructor that initializes the class member variable + + c. + +

    + + class S { int c; public: @@ -83,10 +297,17 @@ public: void f() { S s; int i = s.f(10); -} +} +
    -

    Reading uninitialized variables is undefined behavior and can result in unexpected program behavior. In some cases, these security flaws may allow the execution of arbitrary code.

    +

    + Reading uninitialized variables isย undefined behaviorย and can result inย unexpected program behavior.ย In some cases, these + + security flaws + + may allow the execution of arbitrary code. +

    Clause 5, "Expressions" Subclause 20.2.5, "Function Template - declval + + declval + "
    @@ -123,10 +344,14 @@ void f() { Medium @@ -159,7 +384,9 @@ void f() { 20.10 @@ -224,15 +460,51 @@ void f() { 2021.4 @@ -246,7 +518,9 @@ void f() { @@ -312,7 +588,9 @@ void f() { 4.4 @@ -324,26 +602,62 @@ void f() { @@ -358,7 +672,9 @@ void f() { 20.10
    - P12 + + P12 + - L1 + + L1 +
    - uninitialized-read + + uninitialized-read + Partially checked @@ -175,8 +402,12 @@ void f() { 3.9 - -Wuninitialized - clang-analyzer-core.UndefinedBinaryOperatorResult + + -Wuninitialized + + + clang-analyzer-core.UndefinedBinaryOperatorResult + Does not catch all instances of this rule, such as uninitialized values read from heap-allocated memory. @@ -189,10 +420,13 @@ void f() { - 6.2p0 + 6.1p0 - LANG.STRUCT.RPLLANG.MEM.UVAR + + LANG.STRUCT.RPL + LANG.MEM.UVAR + Return pointer to local @@ -209,7 +443,9 @@ void f() { 2021.2 - C++2726, C++2727, C++2728, C++2961, C++2962, C++2963, C++2966, C++2967, C++2968, C++2971, C++2972, C++2973, C++2976, C++2977, C++2978 + + C++2726, C++2727, C++2728, C++2961, C++2962, C++2963, C++2966, C++2967, C++2968, C++2971, C++2972, C++2973, C++2976, C++2977, C++2978 + - UNINIT.CTOR.MIGHT - UNINIT.CTOR.MUST - UNINIT.HEAP.MIGHT - UNINIT.HEAP.MUST - UNINIT.STACK.ARRAY.MIGHT - UNINIT.STACK.ARRAY.MUST - UNINIT.STACK.ARRAY.PARTIAL.MUST - UNINIT.STACK.MIGHT - UNINIT.STACK.MUST + + + UNINIT.CTOR.MIGHT + + + + + UNINIT.CTOR.MUST + + + + + UNINIT.HEAP.MIGHT + + + + + UNINIT.HEAP.MUST + + + + + UNINIT.STACK.ARRAY.MIGHT + + + + + UNINIT.STACK.ARRAY.MUST + + + + + UNINIT.STACK.ARRAY.PARTIAL.MUST + + + + + UNINIT.STACK.MIGHT + + + + + UNINIT.STACK.MUST + + - 53 D, 69 D, 631 S, 652 S + + 53 D, 69 D, 631 S, 652 S + Partially implemented @@ -262,7 +536,9 @@ void f() { 2021.2 - CERT_CPP-EXP53-a + + CERT_CPP-EXP53-a + Avoid use before initialization @@ -298,7 +574,7 @@ void f() { Checks for: - Non-initialized variableon-initialized variable, non-initialized pointeron-initialized pointer. + Non-initialized variable, non-initialized pointer. Rule partially covered.
    - 2726, 2727, 2728, 2961, 2962, 2963, 2966, 2967, 2968, 2971, 2972, 2973, 2976, 2977, 2978 + + 2726, 2727, 2728, 2961, 2962, 2963, 2966, 2967, 2968, 2971, 2972, 2973, 2976, 2977, 2978 + - 7.17 + 7.16 - V546 + + V546 + + + , - V573 + + V573 + + + , - V614 + + + V614 + + , - V670 + + + V670 + + , - V679 + + + V679 + + , - V730 + + + V730 + + , - V788 + + V788 + + + , - V1007 + + + V1007 + + , - V1050 + + + V1050 + + - uninitialized-read + + uninitialized-read + Partially checked @@ -368,7 +684,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert-standard.qhelp b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert-standard.qhelp index 1e9a428728..47781085bd 100644 --- a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert-standard.qhelp +++ b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert-standard.qhelp @@ -1,31 +1,128 @@
    -

    Every object has a lifetime in which it can be used in a well-defined manner. The lifetime of an object begins when sufficient, properly aligned storage has been obtained for it and its initialization is complete. The lifetime of an object ends when a nontrivial destructor, if any, is called for the object and the storage for the object has been reused or released. Use of an object, or a pointer to an object, outside of its lifetime frequently results in undefined behavior.

    -

    The C++ Standard, [basic.life], paragraph 5 [ISO/IEC 14882-2014], describes the lifetime rules for pointers:

    +

    + Every object has a lifetime in which it can be used in a well-defined manner. The lifetime of an object begins when sufficient, properly aligned storage has been obtained for it and its initialization is complete. The lifetime of an object ends when a nontrivial destructor, if any, is called for the object and the storage for the object has been reused or released. Use of an object, or a pointer to an object, outside of its lifetime frequently results in + + undefined behavior + + . +

    +

    + The C++ Standard,ย [basic.life],ย paragraph 5ย [ + + ISO/IEC 14882-2014 + + ], describes the lifetime rules for pointers: +

    -

    Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a pointer refers to allocated storage, and using the pointer as if the pointer were of type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if: โ€” the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression, โ€” the pointer is used to access a non-static data member or call a non-static member function of the object, or โ€” the pointer is implicitly converted to a pointer to a virtual base class, or โ€” the pointer is used as the operand of a static_cast, except when the conversion is to pointer to cv void, or to pointer to cv void and subsequently to pointer to either cv char or cv unsigned char, or โ€” the pointer is used as the operand of a dynamic_cast.

    +

    + Before the lifetime of an object has started but after the storage which the object will occupy has beenย allocatedย or, after the lifetime of an object has ended and before the storage which the object occupied isย reused or released, any pointer that refers to the storage location where the object will be or was locatedย may be used but only in limited ways. For an object under construction or destruction, see 12.7.ย Otherwise,ย such a pointer refers to allocated storage, and using the pointer as if the pointer were of type + + void* + + ,ย is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used inย limited ways, as described below. The program has undefined behavior if: + โ€” the object will be or was of a class type with a non-trivial destructor and the pointer is used as theย operand of a + + delete-expression + + , + โ€” the pointer is used to access a non-static data member or call a non-static member function of theย object, or + โ€” the pointer is implicitly convertedย to a pointer to a virtual base class, or + โ€” the pointer is used as the operand of a + + static_cast + + , except when the conversion is to pointerย to + + cv + + + void + + , or to pointer to + + cv + + + void + + and subsequently to pointer to either + + cv + + + char + + or + + cv + + + unsignedย char + + , or + โ€” the pointer is used as the operand of a + + dynamic_cast + + . +

    -

    Paragraph 6 describes the lifetime rules for non-pointers:

    +

    + Paragraph 6 describes the lifetime rules for non-pointers: +

    -

    Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a glvalue refers to allocated storage, and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if: โ€” an lvalue-to-rvalue conversion is applied to such a glvalue, โ€” the glvalue is used to access a non-static data member or call a non-static member function of the object, or โ€” the glvalue is bound to a reference to a virtual base class, or โ€” the glvalue is used as the operand of a dynamic_cast or as the operand of typeid.

    +

    + Similarly, before the lifetime of an object has started but after the storage which the object will occupyย has been allocated or, after the lifetime of an object has ended and before the storage which the objectย occupied is reused or released, any glvalue that refers to the original object may be used but only in limitedย ways. For an object under construction or destruction, see 12.7.ย Otherwise, such a glvalue refers to allocatedย storage, and using the properties of the glvalue that do not depend on its value is well-defined. Theย program has undefined behavior if: + โ€” an lvalue-to-rvalue conversionย is applied to such a glvalue, + โ€” the glvalue is used to access a non-static data member or call a non-static member function of theย object, or + โ€” the glvalue is bound to a reference to a virtual base class, or + โ€” the glvalue is used as the operand of a + + dynamic_cast + + or as the operand of + + typeid + + . +

    -

    Do not use an object outside of its lifetime, except in the ways described above as being well-defined.

    +

    + Do not use an object outside of its lifetime, except in the ways described above as being well-defined. +

    -

    In this noncompliant code example, a pointer to an object is used to call a non-static member function of the object prior to the beginning of the pointer's lifetime, resulting in undefined behavior.

    - struct S { +

    + In this noncompliant code example, a pointer to an object is used to call a non-static member function of the object + prior to the beginning of the pointer's lifetime, + resulting in + + undefined behavior + + . +

    + + struct S { void mem_fn(); }; - +ย  void f() { S *s; s->mem_fn(); -} +} +
    -

    In this compliant solution, storage is obtained for the pointer prior to calling S::mem_fn().

    - struct S { +

    + In this compliant solution, storage is obtained for the pointer prior to calling + + S::mem_fn(). + +

    + + struct S { void mem_fn(); }; @@ -33,32 +130,67 @@ void f() { S *s = new S; s->mem_fn(); delete s; -} -

    An improved compliant solution would not dynamically allocate memory directly but would instead use an automatic local variable to obtain the storage and perform initialization. If a pointer were required, use of a smart pointer, such as std::unique_ptr, would be a marked improvement. However, these suggested compliant solutions would distract from the lifetime demonstration of this compliant solution and consequently are not shown.

    +} +
    +

    + An improved compliant solution would not dynamically allocate memory directly but would instead use an automatic local variable to obtain the storage and perform initialization. If a pointer were required, use of a smart pointer, such as + + std::unique_ptr + + , would be a marked improvement. However, these suggested compliant solutions would distract from the lifetime demonstration of this compliant solution and consequently are not shown. +

    -

    In this noncompliant code example, a pointer to an object is implicitly converted to a virtual base class after the object's lifetime has ended, resulting in undefined behavior.

    - struct B {}; - +

    + In this noncompliant code example, a pointer to an object is implicitly converted to a virtual base class after the object's lifetime has ended, resulting in + + undefined behavior + + . +

    + + struct B {}; +ย  struct D1 : virtual B {}; struct D2 : virtual B {}; - +ย  struct S : D1, D2 {}; - +ย  void f(const B *b) {} - +ย  void g() { S *s = new S; // Use s delete s; - +ย  f(s); -} -

    Despite the fact that f() never makes use of the object, its being passed as an argument to f() is sufficient to trigger undefined behavior.

    +} +
    +

    + Despite the factย that + + f() + + never makes use of the object, its being passed as an argument to + + f() + + is sufficient to trigger undefined behavior. +

    -

    In this compliant solution, the lifetime of s is extended to cover the call to f().

    - struct B {}; +

    + In this compliant solution, the lifetime of + + s + + is extended to cover the call to + + f(). + +

    + + struct B {}; struct D1 : virtual B {}; struct D2 : virtual B {}; @@ -71,28 +203,61 @@ void g() { S *s = new S; // Use s f(s); - +ย  delete s; -} +} +
    -

    In this noncompliant code example, the address of a local variable is returned from f(). When the resulting pointer is passed to h(), the lvalue-to-rvalue conversion applied to i results in undefined behavior.

    - int *g() { +

    + In this noncompliant code example, the address of a local variable is returned from + + f() + + . When the resulting pointer is passed to + + h() + + , the lvalue-to-rvalue conversion applied to + + i + + results in + + undefined behavior + + . +

    + + int *g() { int i = 12; return &i; } - +ย  void h(int *i); - +ย  void f() { int *i = g(); h(i); -} -

    Some compilers generate a diagnostic message when a pointer to an object with automatic storage duration is returned from a function, as in this example.

    +} +
    +

    + Some compilers generate a diagnostic message when a pointer to an object with automatic storage duration is returned from a function, as in this example. +

    -

    In this compliant solution, the local variable returned from g() has static storage duration instead of automatic storage duration, extending its lifetime sufficiently for use within f().

    - int *g() { +

    + In this compliant solution, the local variable returned from + + g() + + has static storage duration instead of automatic storage duration, extending its lifetime sufficiently for use within + + f(). + +

    + + int *g() { static int i = 12; return &i; } @@ -103,12 +268,49 @@ void f() { int *i = g(); h(i); } - +
    -

    A std::initializer_list<> object is constructed from an initializer list as though the implementation allocated a temporary array and passed it to the std::initializer_list<> constructor. This temporary array has the same lifetime as other temporary objects except that initializing a std::initializer_list<> object from the array extends the lifetime of the array exactly like binding a reference to a temporary [ISO/IEC 14882-2014].

    -

    In this noncompliant code example, a member variable of type std::initializer_list<int> is list-initialized within the constructor's ctor-initializer. Under these circumstances, the conceptual temporary array's lifetime ends once the constructor exits, so accessing any elements of the std::initializer_list<int> member variable results in undefined behavior.

    - #include <initializer_list> +

    + A + + std::initializer_list<> + + object is constructed from an initializer list as though the implementation allocated a temporary array and passed it to the + + std::initializer_list<> + + constructor. This temporary array has the same lifetime as other temporary objects except that initializing a + + std::initializer_list<> + + object from the array extends the lifetime of the array exactly like binding a reference to a temporary [ + + ISO/IEC 14882-2014 + + ]. +

    +

    + In this noncompliant code example, a member variable of type + + std::initializer_list<int> + + is list-initialized within the constructor's + + ctor-initializer + + . Under these circumstances, the conceptual temporary array's lifetime ends once the constructor exits, so accessing any elements of the + + std::initializer_list<int> + + member variable results in + + undefined behavior + + . +

    + + #include <initializer_list> #include <iostream> class C { @@ -123,11 +325,23 @@ public: void f() { C c; std::cout << c.first(); -} +} +
    -

    In this compliant solution, the std::initializer_list<int> member variable is replaced with a std::vector<int>, which copies the elements of the initializer list to the container instead of relying on a dangling reference to the temporary array.

    - #include <iostream> +

    + In this compliant solution, the + + std::initializer_list<int> + + member variable is replaced with a + + std::vector<int> + + , which copies the elements of the initializer list to the container instead of relying on a dangling reference to the temporary array. +

    + + #include <iostream> #include <vector> class C { @@ -142,23 +356,59 @@ public: void f() { C c; std::cout << c.first(); -} +} +
    -

    In this noncompliant code example, a lambda object is stored in a function object, which is later called (executing the lambda) to obtain a constant reference to a value. The lambda object returns an int value, which is then stored in a temporary int object that becomes bound to the const int & return type specified by the function object. However, the temporary object's lifetime is not extended past the return from the function object's invocation, which causes undefined behavior when the resulting value is accessed.

    - #include <functional> - +

    + In this noncompliant code example, a lambda object is stored in a function object, which is later called (executing the lambda) to obtain a constant reference to a value. The lambda object returns an + + int + + value, which is then stored in a temporary + + int + + object that becomes bound to the + + const int & + + return type specified by the function object. However, the temporary object's lifetime is not extended past the return from the function object's invocation, which causes undefined behavior when the resulting value is accessed. +

    + + #include <functional> +ย  void f() { auto l = [](const int &j) { return j; }; std::function<const int&(const int &)> fn(l); - +ย  int i = 42; int j = fn(i); -} +} +
    -

    In this compliant solution, the std::function object returns an int instead of a const int &, ensuring that the value is copied instead of bound to a temporary reference. An alternative solution would be to call the lambda directly instead of through the std::function<> object.

    - #include <functional> +

    + In this compliant solution, the + + std::function + + object returns an + + int + + instead of a + + const int & + + , ensuring that the value is copied instead of bound to a temporary reference. An alternative solution would be to call the lambda directly instead of through the + + std::function<> + + object. +

    + + #include <functional> void f() { auto l = [](const int &j) { return j; }; @@ -166,64 +416,122 @@ void f() { int i = 42; int j = fn(i); -} +} +
    -

    In this noncompliant code example, the constructor for the automatic variable s is not called because execution does not flow through the declaration of the local variable due to the goto statement. Because the constructor is not called, the lifetime for s has not begun. Therefore, calling S::f() uses the object outside of its lifetime and results in undefined behavior.

    - class S { +

    + In this noncompliant code example, the constructor for the automatic variable + + s + + is not called because execution does not flow through the declaration of the local variable due to the + + goto + + statement. Because the constructor is not called, the lifetime for + + s + + has not begun. Therefore, calling + + S::f() + + uses the object outside of its lifetime and results in undefined behavior. +

    + + class S { int v; - +ย  public: S() : v(12) {} // Non-trivial constructor - +ย  void f(); -}; - +}; ย  +ย  void f() { - - // ... - - goto bad_idea; - +ย  + // ... ย  +ย  + goto bad_idea; ย  +ย  // ... - - S s; // Control passes over the declaration, so initialization does not take place. - +ย  + S s; // Control passes over the declaration, so initialization does not take place. ย  +ย  bad_idea: s.f(); -} +} +
    -

    This compliant solution ensures that s is properly initialized prior to performing the local jump.

    - class S { +

    + This compliant solution ensures that + + s + + is properly initialized prior to performing the local jump. +

    + + class S { int v; - +ย  public: S() : v(12) {} // Non-trivial constructor void f(); -}; - +}; ย  +ย  void f() { S s; - +ย  // ... - +ย  goto bad_idea; - +ย  // ... - +ย  bad_idea: s.f(); -} +} +
    -

    In this noncompliant code example, f() is called with an iterable range of objects of type S. These objects are copied into a temporary buffer using std::copy(), and when processing of those objects is complete, the temporary buffer is deallocated. However, the buffer returned by std::get_temporary_buffer() does not contain initialized objects of type S, so when std::copy() dereferences the destination iterator, it results in undefined behavior because the object referenced by the destination iterator has yet to start its lifetime. This is because while space for the object has been allocated, no constructors or initializers have been invoked.

    - #include <algorithm> +

    + In this noncompliant code example, + + + f() + + + is called with an iterable range of objects of type + + S + + . These objects are copied into a temporary buffer using + + std::copy() + + , and when processing of those objects is complete, the temporary buffer is deallocated. However, the buffer returned by + + std::get_temporary_buffer() + + does not contain initialized objects of type + + S + + , so when + + std::copy() + + dereferences the destination iterator, it results in undefined behavior because the object referencedย by the destination iterator has yet to start its lifetime. This is because while space for the object has been allocated, no constructors or initializers have been invoked. +

    + + #include <algorithm> #include <cstddef> #include <memory> #include <type_traits> - +ย  class S { int i; @@ -258,34 +566,95 @@ void f(Iter i, Iter e) { // Return the temporary memory. std::return_temporary_buffer(vals); -} -

    Implementation Details

    -

    A reasonable implementation of std::get_temporary_buffer() and std::copy() can result in code that behaves like the following example (with error-checking elided).

    - unsigned char *buffer = new (std::nothrow) unsigned char[sizeof(S) * object_count]; +} + +

    + + Implementation Details + +

    +

    + A reasonable implementation of + + std::get_temporary_buffer() + + and + + std::copy() + + can result in code that behaves like the following exampleย (with error-checking elided). +

    + + unsigned char *buffer = new (std::nothrow) unsigned char[sizeof(S) * object_count]; S *result = reinterpret_cast<S *>(buffer); while (i != e) { *result = *i; // Undefined behavior ++result; ++i; -} -

    The act of dereferencing result is undefined behavior because the memory pointed to is not an object of type S within its lifetime.

    +} +
    +

    + The act of dereferencing + + result + + is undefined behavior because the memory pointed to is not an object of type + + S + + within its lifetime. +

    -

    In this compliant solution, std::uninitialized_copy() is used to perform the copy, instead of std::copy(), ensuring that the objects are initialized using placement new instead of dereferencing uninitialized memory. Identical code from the noncompliant code example has been elided for brevity.

    - //... +

    + In this compliant solution, + + std::uninitialized_copy() + + is used to perform the copy, instead of + + std::copy() + + , ensuring that the objects are initialized using placement + + new + + instead of dereferencing uninitialized memory. Identical code from the noncompliant code example has been elided for brevity. +

    + + //... // Copy the values into the memory. std::uninitialized_copy(i, e, vals); -// ... +// ... +
    -

    This compliant solution uses std::copy() with a std::raw_storage_iterator as the destination iterator with the same well-defined results as using std::uninitialized_copy(). As with the previous compliant solution, identical code from the noncompliant code example has been elided for brevity.

    - //... +

    + This compliant solution uses + + std::copy() + + withย a + + std::raw_storage_iterator + + as the destination iterator with the same well-defined results as using + + std::uninitialized_copy() + + . As with the previous compliant solution, identical code from the noncompliant code example has been elided for brevity. +

    + + //... // Copy the values into the memory. std::copy(i, e, std::raw_storage_iterator<S*, S>(vals)); -// ... +// ... +
    -

    Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code.

    +

    + Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code. +

    @@ -322,10 +691,14 @@ while (i != e) { High @@ -358,7 +731,10 @@ while (i != e) { 20.10 @@ -388,10 +768,13 @@ while (i != e) { @@ -423,26 +808,106 @@ while (i != e) { 2021.4 @@ -456,7 +921,9 @@ while (i != e) { @@ -526,8 +999,12 @@ while (i != e) { 4.4 @@ -539,10 +1016,18 @@ while (i != e) { @@ -557,7 +1042,9 @@ while (i != e) { 20.10
    - P6 + + P6 + - L2 + + L2 +
    - return-reference-localdangling_pointer_use + + return-reference-local + dangling_pointer_use + Partially checked @@ -374,11 +750,15 @@ while (i != e) { 3.9 - -Wdangling-initializer-list + + -Wdangling-initializer-list + Catches some lifetime issues related to incorrect use of - std::initializer_list<> + + std::initializer_list<> +
    - 6.2p0 + 6.1p0 - IO.UACALLOC.UAF + + IO.UAC + ALLOC.UAF + Use after close @@ -408,7 +791,9 @@ while (i != e) { 2021.2 - C++2812, C++2813, C++2814, C++2930, C++2931, C++2932, C++2933, C++2934, C++4003, C++4026 + + C++2812, C++2813, C++2814, C++2930, C++2931, C++2932, C++2933, C++2934, C++4003, C++4026 + - CL.FFM.ASSIGN - CL.FFM.COPY - LOCRET.ARG - LOCRET.GLOB - LOCRET.RET - UFM.DEREF.MIGHT - UFM.DEREF.MUST - UFM.FFM.MIGHT - UFM.FFM.MUST - UFM.RETURN.MIGHT - UFM.RETURN.MUST - UFM.USE.MIGHT - UFM.USE.MUST - UNINIT.HEAP.MIGHT - UNINIT.HEAP.MUST - UNINIT.STACK.ARRAY.MIGHT - UNINIT.STACK.ARRAY.MUST - UNINIT.STACK.ARRAY.PARTIAL.MUST - UNINIT.STACK.MIGHT - UNINIT.STACK.MUST + + + CL.FFM.ASSIGN + + + + + CL.FFM.COPY + + + + + LOCRET.ARG + + + + + LOCRET.GLOB + + + + + LOCRET.RET + + + + + UFM.DEREF.MIGHT + + + + + UFM.DEREF.MUST + + + + + UFM.FFM.MIGHT + + + + + UFM.FFM.MUST + + + + + UFM.RETURN.MIGHT + + + + + UFM.RETURN.MUST + + + + + UFM.USE.MIGHT + + + + + UFM.USE.MUST + + + + + UNINIT.HEAP.MIGHT + + + + + UNINIT.HEAP.MUST + + + + + UNINIT.STACK.ARRAY.MIGHT + + + + + UNINIT.STACK.ARRAY.MUST + + + + + UNINIT.STACK.ARRAY.PARTIAL.MUST + + + + + UNINIT.STACK.MIGHT + + + + + UNINIT.STACK.MUST + + - 42 D, 53 D, 77 D, 1 J, 71 S, 565 S + + 42 D, 53 D, 77 D, 1 J, 71 S, 565 S + Partially implemented @@ -472,9 +939,15 @@ while (i != e) { 2021.2 - CERT_CPP-EXP54-a - CERT_CPP-EXP54-b - CERT_CPP-EXP54-c + + CERT_CPP-EXP54-a + + + CERT_CPP-EXP54-b + + + CERT_CPP-EXP54-c + Do not use resources that have been freed @@ -512,7 +985,7 @@ while (i != e) { Checks for: - Non-initialized variable or pointeron-initialized variable or pointer, use of previously freed pointerse of previously freed pointer, pointer or reference to stack variable leaving scopeointer or reference to stack variable leaving scope, accessing object with temporary lifetimeccessing object with temporary lifetime. + Non-initialized variable or pointer, use of previously freed pointer, pointer or reference to stack variable leaving scope, accessing object with temporary lifetime. Rule partially covered.
    - 2812, 2813, 2814, 2930, 2931, - 2932, 2933, 2934, 4003, 4026 + + 2812, 2813, 2814, 2930, 2931, + + + 2932, 2933, 2934, 4003, 4026 + - 7.17 + 7.16 - V758, V1041 + + + V758 + + , + + V1041 + + - return-reference-local + + return-reference-local + Partially checked @@ -567,7 +1054,17 @@ while (i != e) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql index 4f72fc725a..7408b99dbf 100644 --- a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql +++ b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedAfterLifetimeCert.ql @@ -8,6 +8,7 @@ * @tags external/cert/id/exp54-cpp * correctness * security + * external/autosar/default-disabled * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert-standard.qhelp b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert-standard.qhelp index 1e9a428728..47781085bd 100644 --- a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert-standard.qhelp +++ b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert-standard.qhelp @@ -1,31 +1,128 @@
    -

    Every object has a lifetime in which it can be used in a well-defined manner. The lifetime of an object begins when sufficient, properly aligned storage has been obtained for it and its initialization is complete. The lifetime of an object ends when a nontrivial destructor, if any, is called for the object and the storage for the object has been reused or released. Use of an object, or a pointer to an object, outside of its lifetime frequently results in undefined behavior.

    -

    The C++ Standard, [basic.life], paragraph 5 [ISO/IEC 14882-2014], describes the lifetime rules for pointers:

    +

    + Every object has a lifetime in which it can be used in a well-defined manner. The lifetime of an object begins when sufficient, properly aligned storage has been obtained for it and its initialization is complete. The lifetime of an object ends when a nontrivial destructor, if any, is called for the object and the storage for the object has been reused or released. Use of an object, or a pointer to an object, outside of its lifetime frequently results in + + undefined behavior + + . +

    +

    + The C++ Standard,ย [basic.life],ย paragraph 5ย [ + + ISO/IEC 14882-2014 + + ], describes the lifetime rules for pointers: +

    -

    Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that refers to the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a pointer refers to allocated storage, and using the pointer as if the pointer were of type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below. The program has undefined behavior if: โ€” the object will be or was of a class type with a non-trivial destructor and the pointer is used as the operand of a delete-expression, โ€” the pointer is used to access a non-static data member or call a non-static member function of the object, or โ€” the pointer is implicitly converted to a pointer to a virtual base class, or โ€” the pointer is used as the operand of a static_cast, except when the conversion is to pointer to cv void, or to pointer to cv void and subsequently to pointer to either cv char or cv unsigned char, or โ€” the pointer is used as the operand of a dynamic_cast.

    +

    + Before the lifetime of an object has started but after the storage which the object will occupy has beenย allocatedย or, after the lifetime of an object has ended and before the storage which the object occupied isย reused or released, any pointer that refers to the storage location where the object will be or was locatedย may be used but only in limited ways. For an object under construction or destruction, see 12.7.ย Otherwise,ย such a pointer refers to allocated storage, and using the pointer as if the pointer were of type + + void* + + ,ย is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used inย limited ways, as described below. The program has undefined behavior if: + โ€” the object will be or was of a class type with a non-trivial destructor and the pointer is used as theย operand of a + + delete-expression + + , + โ€” the pointer is used to access a non-static data member or call a non-static member function of theย object, or + โ€” the pointer is implicitly convertedย to a pointer to a virtual base class, or + โ€” the pointer is used as the operand of a + + static_cast + + , except when the conversion is to pointerย to + + cv + + + void + + , or to pointer to + + cv + + + void + + and subsequently to pointer to either + + cv + + + char + + or + + cv + + + unsignedย char + + , or + โ€” the pointer is used as the operand of a + + dynamic_cast + + . +

    -

    Paragraph 6 describes the lifetime rules for non-pointers:

    +

    + Paragraph 6 describes the lifetime rules for non-pointers: +

    -

    Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a glvalue refers to allocated storage, and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if: โ€” an lvalue-to-rvalue conversion is applied to such a glvalue, โ€” the glvalue is used to access a non-static data member or call a non-static member function of the object, or โ€” the glvalue is bound to a reference to a virtual base class, or โ€” the glvalue is used as the operand of a dynamic_cast or as the operand of typeid.

    +

    + Similarly, before the lifetime of an object has started but after the storage which the object will occupyย has been allocated or, after the lifetime of an object has ended and before the storage which the objectย occupied is reused or released, any glvalue that refers to the original object may be used but only in limitedย ways. For an object under construction or destruction, see 12.7.ย Otherwise, such a glvalue refers to allocatedย storage, and using the properties of the glvalue that do not depend on its value is well-defined. Theย program has undefined behavior if: + โ€” an lvalue-to-rvalue conversionย is applied to such a glvalue, + โ€” the glvalue is used to access a non-static data member or call a non-static member function of theย object, or + โ€” the glvalue is bound to a reference to a virtual base class, or + โ€” the glvalue is used as the operand of a + + dynamic_cast + + or as the operand of + + typeid + + . +

    -

    Do not use an object outside of its lifetime, except in the ways described above as being well-defined.

    +

    + Do not use an object outside of its lifetime, except in the ways described above as being well-defined. +

    -

    In this noncompliant code example, a pointer to an object is used to call a non-static member function of the object prior to the beginning of the pointer's lifetime, resulting in undefined behavior.

    - struct S { +

    + In this noncompliant code example, a pointer to an object is used to call a non-static member function of the object + prior to the beginning of the pointer's lifetime, + resulting in + + undefined behavior + + . +

    + + struct S { void mem_fn(); }; - +ย  void f() { S *s; s->mem_fn(); -} +} +
    -

    In this compliant solution, storage is obtained for the pointer prior to calling S::mem_fn().

    - struct S { +

    + In this compliant solution, storage is obtained for the pointer prior to calling + + S::mem_fn(). + +

    + + struct S { void mem_fn(); }; @@ -33,32 +130,67 @@ void f() { S *s = new S; s->mem_fn(); delete s; -} -

    An improved compliant solution would not dynamically allocate memory directly but would instead use an automatic local variable to obtain the storage and perform initialization. If a pointer were required, use of a smart pointer, such as std::unique_ptr, would be a marked improvement. However, these suggested compliant solutions would distract from the lifetime demonstration of this compliant solution and consequently are not shown.

    +} +
    +

    + An improved compliant solution would not dynamically allocate memory directly but would instead use an automatic local variable to obtain the storage and perform initialization. If a pointer were required, use of a smart pointer, such as + + std::unique_ptr + + , would be a marked improvement. However, these suggested compliant solutions would distract from the lifetime demonstration of this compliant solution and consequently are not shown. +

    -

    In this noncompliant code example, a pointer to an object is implicitly converted to a virtual base class after the object's lifetime has ended, resulting in undefined behavior.

    - struct B {}; - +

    + In this noncompliant code example, a pointer to an object is implicitly converted to a virtual base class after the object's lifetime has ended, resulting in + + undefined behavior + + . +

    + + struct B {}; +ย  struct D1 : virtual B {}; struct D2 : virtual B {}; - +ย  struct S : D1, D2 {}; - +ย  void f(const B *b) {} - +ย  void g() { S *s = new S; // Use s delete s; - +ย  f(s); -} -

    Despite the fact that f() never makes use of the object, its being passed as an argument to f() is sufficient to trigger undefined behavior.

    +} +
    +

    + Despite the factย that + + f() + + never makes use of the object, its being passed as an argument to + + f() + + is sufficient to trigger undefined behavior. +

    -

    In this compliant solution, the lifetime of s is extended to cover the call to f().

    - struct B {}; +

    + In this compliant solution, the lifetime of + + s + + is extended to cover the call to + + f(). + +

    + + struct B {}; struct D1 : virtual B {}; struct D2 : virtual B {}; @@ -71,28 +203,61 @@ void g() { S *s = new S; // Use s f(s); - +ย  delete s; -} +} +
    -

    In this noncompliant code example, the address of a local variable is returned from f(). When the resulting pointer is passed to h(), the lvalue-to-rvalue conversion applied to i results in undefined behavior.

    - int *g() { +

    + In this noncompliant code example, the address of a local variable is returned from + + f() + + . When the resulting pointer is passed to + + h() + + , the lvalue-to-rvalue conversion applied to + + i + + results in + + undefined behavior + + . +

    + + int *g() { int i = 12; return &i; } - +ย  void h(int *i); - +ย  void f() { int *i = g(); h(i); -} -

    Some compilers generate a diagnostic message when a pointer to an object with automatic storage duration is returned from a function, as in this example.

    +} +
    +

    + Some compilers generate a diagnostic message when a pointer to an object with automatic storage duration is returned from a function, as in this example. +

    -

    In this compliant solution, the local variable returned from g() has static storage duration instead of automatic storage duration, extending its lifetime sufficiently for use within f().

    - int *g() { +

    + In this compliant solution, the local variable returned from + + g() + + has static storage duration instead of automatic storage duration, extending its lifetime sufficiently for use within + + f(). + +

    + + int *g() { static int i = 12; return &i; } @@ -103,12 +268,49 @@ void f() { int *i = g(); h(i); } - +
    -

    A std::initializer_list<> object is constructed from an initializer list as though the implementation allocated a temporary array and passed it to the std::initializer_list<> constructor. This temporary array has the same lifetime as other temporary objects except that initializing a std::initializer_list<> object from the array extends the lifetime of the array exactly like binding a reference to a temporary [ISO/IEC 14882-2014].

    -

    In this noncompliant code example, a member variable of type std::initializer_list<int> is list-initialized within the constructor's ctor-initializer. Under these circumstances, the conceptual temporary array's lifetime ends once the constructor exits, so accessing any elements of the std::initializer_list<int> member variable results in undefined behavior.

    - #include <initializer_list> +

    + A + + std::initializer_list<> + + object is constructed from an initializer list as though the implementation allocated a temporary array and passed it to the + + std::initializer_list<> + + constructor. This temporary array has the same lifetime as other temporary objects except that initializing a + + std::initializer_list<> + + object from the array extends the lifetime of the array exactly like binding a reference to a temporary [ + + ISO/IEC 14882-2014 + + ]. +

    +

    + In this noncompliant code example, a member variable of type + + std::initializer_list<int> + + is list-initialized within the constructor's + + ctor-initializer + + . Under these circumstances, the conceptual temporary array's lifetime ends once the constructor exits, so accessing any elements of the + + std::initializer_list<int> + + member variable results in + + undefined behavior + + . +

    + + #include <initializer_list> #include <iostream> class C { @@ -123,11 +325,23 @@ public: void f() { C c; std::cout << c.first(); -} +} +
    -

    In this compliant solution, the std::initializer_list<int> member variable is replaced with a std::vector<int>, which copies the elements of the initializer list to the container instead of relying on a dangling reference to the temporary array.

    - #include <iostream> +

    + In this compliant solution, the + + std::initializer_list<int> + + member variable is replaced with a + + std::vector<int> + + , which copies the elements of the initializer list to the container instead of relying on a dangling reference to the temporary array. +

    + + #include <iostream> #include <vector> class C { @@ -142,23 +356,59 @@ public: void f() { C c; std::cout << c.first(); -} +} +
    -

    In this noncompliant code example, a lambda object is stored in a function object, which is later called (executing the lambda) to obtain a constant reference to a value. The lambda object returns an int value, which is then stored in a temporary int object that becomes bound to the const int & return type specified by the function object. However, the temporary object's lifetime is not extended past the return from the function object's invocation, which causes undefined behavior when the resulting value is accessed.

    - #include <functional> - +

    + In this noncompliant code example, a lambda object is stored in a function object, which is later called (executing the lambda) to obtain a constant reference to a value. The lambda object returns an + + int + + value, which is then stored in a temporary + + int + + object that becomes bound to the + + const int & + + return type specified by the function object. However, the temporary object's lifetime is not extended past the return from the function object's invocation, which causes undefined behavior when the resulting value is accessed. +

    + + #include <functional> +ย  void f() { auto l = [](const int &j) { return j; }; std::function<const int&(const int &)> fn(l); - +ย  int i = 42; int j = fn(i); -} +} +
    -

    In this compliant solution, the std::function object returns an int instead of a const int &, ensuring that the value is copied instead of bound to a temporary reference. An alternative solution would be to call the lambda directly instead of through the std::function<> object.

    - #include <functional> +

    + In this compliant solution, the + + std::function + + object returns an + + int + + instead of a + + const int & + + , ensuring that the value is copied instead of bound to a temporary reference. An alternative solution would be to call the lambda directly instead of through the + + std::function<> + + object. +

    + + #include <functional> void f() { auto l = [](const int &j) { return j; }; @@ -166,64 +416,122 @@ void f() { int i = 42; int j = fn(i); -} +} +
    -

    In this noncompliant code example, the constructor for the automatic variable s is not called because execution does not flow through the declaration of the local variable due to the goto statement. Because the constructor is not called, the lifetime for s has not begun. Therefore, calling S::f() uses the object outside of its lifetime and results in undefined behavior.

    - class S { +

    + In this noncompliant code example, the constructor for the automatic variable + + s + + is not called because execution does not flow through the declaration of the local variable due to the + + goto + + statement. Because the constructor is not called, the lifetime for + + s + + has not begun. Therefore, calling + + S::f() + + uses the object outside of its lifetime and results in undefined behavior. +

    + + class S { int v; - +ย  public: S() : v(12) {} // Non-trivial constructor - +ย  void f(); -}; - +}; ย  +ย  void f() { - - // ... - - goto bad_idea; - +ย  + // ... ย  +ย  + goto bad_idea; ย  +ย  // ... - - S s; // Control passes over the declaration, so initialization does not take place. - +ย  + S s; // Control passes over the declaration, so initialization does not take place. ย  +ย  bad_idea: s.f(); -} +} +
    -

    This compliant solution ensures that s is properly initialized prior to performing the local jump.

    - class S { +

    + This compliant solution ensures that + + s + + is properly initialized prior to performing the local jump. +

    + + class S { int v; - +ย  public: S() : v(12) {} // Non-trivial constructor void f(); -}; - +}; ย  +ย  void f() { S s; - +ย  // ... - +ย  goto bad_idea; - +ย  // ... - +ย  bad_idea: s.f(); -} +} +
    -

    In this noncompliant code example, f() is called with an iterable range of objects of type S. These objects are copied into a temporary buffer using std::copy(), and when processing of those objects is complete, the temporary buffer is deallocated. However, the buffer returned by std::get_temporary_buffer() does not contain initialized objects of type S, so when std::copy() dereferences the destination iterator, it results in undefined behavior because the object referenced by the destination iterator has yet to start its lifetime. This is because while space for the object has been allocated, no constructors or initializers have been invoked.

    - #include <algorithm> +

    + In this noncompliant code example, + + + f() + + + is called with an iterable range of objects of type + + S + + . These objects are copied into a temporary buffer using + + std::copy() + + , and when processing of those objects is complete, the temporary buffer is deallocated. However, the buffer returned by + + std::get_temporary_buffer() + + does not contain initialized objects of type + + S + + , so when + + std::copy() + + dereferences the destination iterator, it results in undefined behavior because the object referencedย by the destination iterator has yet to start its lifetime. This is because while space for the object has been allocated, no constructors or initializers have been invoked. +

    + + #include <algorithm> #include <cstddef> #include <memory> #include <type_traits> - +ย  class S { int i; @@ -258,34 +566,95 @@ void f(Iter i, Iter e) { // Return the temporary memory. std::return_temporary_buffer(vals); -} -

    Implementation Details

    -

    A reasonable implementation of std::get_temporary_buffer() and std::copy() can result in code that behaves like the following example (with error-checking elided).

    - unsigned char *buffer = new (std::nothrow) unsigned char[sizeof(S) * object_count]; +} + +

    + + Implementation Details + +

    +

    + A reasonable implementation of + + std::get_temporary_buffer() + + and + + std::copy() + + can result in code that behaves like the following exampleย (with error-checking elided). +

    + + unsigned char *buffer = new (std::nothrow) unsigned char[sizeof(S) * object_count]; S *result = reinterpret_cast<S *>(buffer); while (i != e) { *result = *i; // Undefined behavior ++result; ++i; -} -

    The act of dereferencing result is undefined behavior because the memory pointed to is not an object of type S within its lifetime.

    +} +
    +

    + The act of dereferencing + + result + + is undefined behavior because the memory pointed to is not an object of type + + S + + within its lifetime. +

    -

    In this compliant solution, std::uninitialized_copy() is used to perform the copy, instead of std::copy(), ensuring that the objects are initialized using placement new instead of dereferencing uninitialized memory. Identical code from the noncompliant code example has been elided for brevity.

    - //... +

    + In this compliant solution, + + std::uninitialized_copy() + + is used to perform the copy, instead of + + std::copy() + + , ensuring that the objects are initialized using placement + + new + + instead of dereferencing uninitialized memory. Identical code from the noncompliant code example has been elided for brevity. +

    + + //... // Copy the values into the memory. std::uninitialized_copy(i, e, vals); -// ... +// ... +
    -

    This compliant solution uses std::copy() with a std::raw_storage_iterator as the destination iterator with the same well-defined results as using std::uninitialized_copy(). As with the previous compliant solution, identical code from the noncompliant code example has been elided for brevity.

    - //... +

    + This compliant solution uses + + std::copy() + + withย a + + std::raw_storage_iterator + + as the destination iterator with the same well-defined results as using + + std::uninitialized_copy() + + . As with the previous compliant solution, identical code from the noncompliant code example has been elided for brevity. +

    + + //... // Copy the values into the memory. std::copy(i, e, std::raw_storage_iterator<S*, S>(vals)); -// ... +// ... +
    -

    Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code.

    +

    + Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code. +

    @@ -322,10 +691,14 @@ while (i != e) { High @@ -358,7 +731,10 @@ while (i != e) { 20.10 @@ -388,10 +768,13 @@ while (i != e) { @@ -423,26 +808,106 @@ while (i != e) { 2021.4 @@ -456,7 +921,9 @@ while (i != e) { @@ -526,8 +999,12 @@ while (i != e) { 4.4 @@ -539,10 +1016,18 @@ while (i != e) { @@ -557,7 +1042,9 @@ while (i != e) { 20.10
    - P6 + + P6 + - L2 + + L2 +
    - return-reference-localdangling_pointer_use + + return-reference-local + dangling_pointer_use + Partially checked @@ -374,11 +750,15 @@ while (i != e) { 3.9 - -Wdangling-initializer-list + + -Wdangling-initializer-list + Catches some lifetime issues related to incorrect use of - std::initializer_list<> + + std::initializer_list<> +
    - 6.2p0 + 6.1p0 - IO.UACALLOC.UAF + + IO.UAC + ALLOC.UAF + Use after close @@ -408,7 +791,9 @@ while (i != e) { 2021.2 - C++2812, C++2813, C++2814, C++2930, C++2931, C++2932, C++2933, C++2934, C++4003, C++4026 + + C++2812, C++2813, C++2814, C++2930, C++2931, C++2932, C++2933, C++2934, C++4003, C++4026 + - CL.FFM.ASSIGN - CL.FFM.COPY - LOCRET.ARG - LOCRET.GLOB - LOCRET.RET - UFM.DEREF.MIGHT - UFM.DEREF.MUST - UFM.FFM.MIGHT - UFM.FFM.MUST - UFM.RETURN.MIGHT - UFM.RETURN.MUST - UFM.USE.MIGHT - UFM.USE.MUST - UNINIT.HEAP.MIGHT - UNINIT.HEAP.MUST - UNINIT.STACK.ARRAY.MIGHT - UNINIT.STACK.ARRAY.MUST - UNINIT.STACK.ARRAY.PARTIAL.MUST - UNINIT.STACK.MIGHT - UNINIT.STACK.MUST + + + CL.FFM.ASSIGN + + + + + CL.FFM.COPY + + + + + LOCRET.ARG + + + + + LOCRET.GLOB + + + + + LOCRET.RET + + + + + UFM.DEREF.MIGHT + + + + + UFM.DEREF.MUST + + + + + UFM.FFM.MIGHT + + + + + UFM.FFM.MUST + + + + + UFM.RETURN.MIGHT + + + + + UFM.RETURN.MUST + + + + + UFM.USE.MIGHT + + + + + UFM.USE.MUST + + + + + UNINIT.HEAP.MIGHT + + + + + UNINIT.HEAP.MUST + + + + + UNINIT.STACK.ARRAY.MIGHT + + + + + UNINIT.STACK.ARRAY.MUST + + + + + UNINIT.STACK.ARRAY.PARTIAL.MUST + + + + + UNINIT.STACK.MIGHT + + + + + UNINIT.STACK.MUST + + - 42 D, 53 D, 77 D, 1 J, 71 S, 565 S + + 42 D, 53 D, 77 D, 1 J, 71 S, 565 S + Partially implemented @@ -472,9 +939,15 @@ while (i != e) { 2021.2 - CERT_CPP-EXP54-a - CERT_CPP-EXP54-b - CERT_CPP-EXP54-c + + CERT_CPP-EXP54-a + + + CERT_CPP-EXP54-b + + + CERT_CPP-EXP54-c + Do not use resources that have been freed @@ -512,7 +985,7 @@ while (i != e) { Checks for: - Non-initialized variable or pointeron-initialized variable or pointer, use of previously freed pointerse of previously freed pointer, pointer or reference to stack variable leaving scopeointer or reference to stack variable leaving scope, accessing object with temporary lifetimeccessing object with temporary lifetime. + Non-initialized variable or pointer, use of previously freed pointer, pointer or reference to stack variable leaving scope, accessing object with temporary lifetime. Rule partially covered.
    - 2812, 2813, 2814, 2930, 2931, - 2932, 2933, 2934, 4003, 4026 + + 2812, 2813, 2814, 2930, 2931, + + + 2932, 2933, 2934, 4003, 4026 + - 7.17 + 7.16 - V758, V1041 + + + V758 + + , + + V1041 + + - return-reference-local + + return-reference-local + Partially checked @@ -567,7 +1054,17 @@ while (i != e) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql index d97c002dbd..07a99eb44d 100644 --- a/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql +++ b/cpp/cert/src/rules/EXP54-CPP/ObjectAccessedBeforeLifetimeCert.ql @@ -8,6 +8,7 @@ * @tags external/cert/id/exp54-cpp * correctness * security + * external/autosar/default-disabled * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert-standard.qhelp b/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert-standard.qhelp index 9639961b58..ea3ee4b8c0 100644 --- a/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert-standard.qhelp +++ b/cpp/cert/src/rules/EXP55-CPP/RemoveConstOrVolatileQualificationCert-standard.qhelp @@ -1,19 +1,72 @@
    -

    The C++ Standard, [dcl.type.cv], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [dcl.type.cv], paragraph 4ย [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

    +

    + Except that any class member declared + + mutable + + can be modified, any attempt to modify a + + const + + object during its lifetime results in undefined behavior. +

    -

    Similarly, paragraph 6 states the following:

    +

    + Similarly, paragraph 6 states the following: +

    -

    What constitutes an access to an object that has volatile-qualified type is implementation-defined. If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined.

    +

    + What constitutes an access to an object that has volatile-qualified type is implementation-defined. If anย attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue withย a non-volatile-qualified type, the program behavior is undefined. +

    -

    Do not cast away a const qualification to attempt to modify the resulting object. The const qualifier implies that the API designer does not intend for that object to be modified despite the possibility it may be modifiable. Do not cast away a volatile qualification; the volatile qualifier implies that the API designer intends the object to be accessed in ways unknown to the compiler, and any access of the volatile object results in undefined behavior.

    +

    + Do not cast away a + + const + + qualification to attempt to modify the resulting object. The + + const + + qualifier implies that the API designer does not intend for that object to be modified despite the possibility it may be modifiable. Do not cast away a + + volatile + + qualification; the + + volatile + + qualifier implies that the API designer intends the object to be accessed in ways unknown to the compiler, and any access of the volatile object results in + + undefined behavior + + . +

    -

    In this noncompliant code example, the function g() is passed a const int &, which is then cast to an int & and modified. Because the referenced value was previously declared as const, the assignment operation results in undefined behavior.

    - void g(const int &ci) { +

    + In this noncompliant code example, the function + + g + + () is passed a const int &, which is then cast to an int & and modified. Because the referenced value was previously declared asย const, the assignment operation results in + + undefined behavior + + . +

    + + void g(const int &ci) { int &ir = const_cast<int &>(ci); ir = 42; } @@ -21,11 +74,27 @@ void f() { const int i = 4; g(i); -} +} +
    -

    In this compliant solution, the function g() is passed an int &, and the caller is required to pass an int that can be modified.

    - void g(int &i) { +

    + In this compliant solution, the function + + g() + + is passed an + + int & + + , and the caller is required to pass an + + int + + that can be modified. +

    + + void g(int &i) { i = 42; } @@ -33,12 +102,43 @@ void f() { int i = 4; g(i); } - +
    -

    In this noncompliant code example, a const-qualified method is called that attempts to cache results by casting away the const-qualifier of this. Because s was declared const, the mutation of cachedValue results in undefined behavior.

    - #include <iostream> - +

    + In this noncompliant code example, a + + const + + -qualified method is called that attempts to cache results by casting away the + + const + + -qualifier of + + this + + . Because + + s + + was declared + + const + + , the mutation of + + cachedValue + + results in + + undefined behavior + + . +

    + + #include <iostream> +ย  class S { int cachedValue; @@ -58,11 +158,37 @@ public: void f() { const S s; std::cout << s.get_value() << std::endl; -} +} +
    -

    This compliant solution uses the mutable keyword when declaring cachedValue, which allows cachedValue to be mutated within a const context without triggering undefined behavior.

    - #include <iostream> +

    + This compliant solution uses the + + + mutable + + + keyword when declaring + + cachedValue + + , which allows + + cachedValue + + to be mutated within a + + const + + context without triggering + + undefined behavior + + . +

    + + #include <iostream> class S { mutable int cachedValue; @@ -83,11 +209,31 @@ public: void f() { const S s; std::cout << s.get_value() << std::endl; -} +} +
    -

    In this noncompliant code example, the volatile value s has the volatile qualifier cast away, and an attempt is made to read the value within g(), resulting in undefined behavior.

    - #include <iostream> +

    + In this noncompliant code example, the volatile value + + s + + has the + + volatile + + qualifier cast away, and an attempt is made to read the value within + + g() + + , resulting in + + undefined behavior + + . +

    + + #include <iostream> struct S { int i; @@ -102,11 +248,26 @@ void g(S &s) { void f() { volatile S s(12); g(const_cast<S &>(s)); -} +} +
    -

    This compliant solution assumes that the volatility of s is required, so g() is modified to accept a volatile S &.

    - #include <iostream> +

    + This compliant solution assumes that the volatility of + + s + + is required, so + + g() + + is modified to accept a + + volatile S &. + +

    + + #include <iostream> struct S { int i; @@ -121,21 +282,63 @@ void g(volatile S &s) { void f() { volatile S s(12); g(s); -} +} +
    -

    EXP55-CPP-EX1: An exception to this rule is allowed when it is necessary to cast away const when invoking a legacy API that does not accept a const argument, provided the function does not attempt to modify the referenced variable. However, it is always preferable to modify the API to be const-correct when possible. For example, the following code casts away the const qualification of INVFNAME in the call to the audit_log() function.

    - // Legacy function defined elsewhere - cannot be modified; does not attempt to +

    + + EXP55-CPP-EX1: + + An exception to this rule is allowed when it is necessary to cast away + + const + + when invoking a legacy API that does not accept a + + const + + argument, provided the function does not attempt to modify the referenced variable. However, it is always preferable to modify the API to be + + const + + -correct when possible.ย For example, the following code casts away the + + const + + qualification of + + INVFNAME + + in the call to the + + audit_log() + + function. +

    + + // Legacy function defined elsewhere - cannot be modified; does not attempt to // modify the contents of the passed parameter. void audit_log(char *errstr); void f() { const char INVFNAME[] = "Invalid file name."; audit_log(const_cast<char *>(INVFNAME)); -} +} +
    -

    If the object is declared as being constant, it may reside in write-protected memory at runtime. Attempting to modify such an object may lead to abnormal program termination or a denial-of-service attack. If an object is declared as being volatile, the compiler can make no assumptions regarding access of that object. Casting away the volatility of an object can result in reads or writes to the object being reordered or elided entirely, resulting in abnormal program execution.

    +

    + If the object is declared as being constant, it may reside in write-protected memory at runtime. Attempting to modify such an object may lead to + + abnormal program termination + + or a + + denial-of-service attack + + . If an object is declared as being volatile, the compiler can make no assumptions regarding access of that object. Casting away the volatility of an object can result in reads or writes to the object being reordered or elided entirely, resulting in abnormal program execution. +

    @@ -172,10 +375,14 @@ void f() { Medium @@ -208,7 +415,10 @@ void f() { 20.10 @@ -239,7 +451,9 @@ void f() { 2021.2 @@ -254,7 +468,11 @@ void f() { 2021.4 @@ -268,7 +486,9 @@ void f() { @@ -333,7 +557,10 @@ void f() { 20.10 @@ -358,7 +589,17 @@ void f() {
    - P8 + + P8 + - L2 + + L2 +
    - pointer-qualifier-cast-constpointer-qualifier-cast-volatile + + pointer-qualifier-cast-const + pointer-qualifier-cast-volatile + Partially checked @@ -224,7 +434,9 @@ void f() { 7.2.0 - CertC++-EXP55 + + CertC++-EXP55 + - C++3066, C++4671 + + C++3066, C++4671 + - MISRA.CAST.CONST + + + MISRA.CAST.CONST + + - 203 S, 242 S, 344 S + + 203 S, 242 S, 344 S + Fully implemented @@ -284,7 +504,9 @@ void f() { 2021.2 - CERT_CPP-EXP55-a + + CERT_CPP-EXP55-a + A cast shall not remove any 'const' or 'volatile' qualification from the type of a pointer or reference @@ -318,7 +540,9 @@ void f() { 4.4 - 3066, 4671 + + 3066, 4671 + - pointer-qualifier-cast-constpointer-qualifier-cast-volatile + + pointer-qualifier-cast-const + pointer-qualifier-cast-volatile + Partially checked @@ -349,7 +576,11 @@ void f() { 4.10 - S859 + + + S859 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -410,7 +651,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage-standard.qhelp b/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage-standard.qhelp index 52c977d290..58b771b147 100644 --- a/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage-standard.qhelp +++ b/cpp/cert/src/rules/EXP56-CPP/FunctionWithMismatchedLanguageLinkage-standard.qhelp @@ -1,22 +1,108 @@
    -

    C++ allows a degree of interoperability with other languages through the use of language linkage specifications. These specifications affect the way in which functions are called or data is accessed. By default, all function types, as well as function and variable names, with external linkage have C++ language linkage, though a different language linkage may be specified. Implementations are required to support "C" and "C++" as a language linkage, but other language linkages exist with implementation-defined semantics, such as "java", "Ada", and "FORTRAN".

    -

    Language linkage is specified to be part of the function type, according to the C++ Standard, [dcl.link], paragraph 1 [ISO/IEC 14882-2014], which, in part, states the following:

    +

    + C++ allows a degree of interoperability with other languages through the use of language linkage specifications. These specifications affect the way in which functions are called or data is accessed. By default, all function types, as well as function and variable names, with external linkage have C++ language linkage, though a different language linkage may be specified. Implementations are required to support + + "C" and + + "C++" + + + as a language linkage, but other language linkages exist with implementation-defined semantics, such as + + "java" + + , + + "Ada" + + , and + + "FORTRAN" + + . +

    +

    + Language linkage is specified to be part of the function type, according to the C++ Standard,ย [dcl.link], paragraph 1ย [ + + ISO/IEC 14882-2014 + + ], which, in part, states the following: +

    -

    Two function types with different language linkages are distinct types even if they are otherwise identical.

    +

    + Two function types with different languageย linkages are distinct types even if they are otherwise identical. +

    -

    When calling a function, it is undefined behavior if the language linkage of the function type used in the call does not match the language linkage of the function definition. For instance, a mismatch in language linkage specification may corrupt the call stack due to calling conventions or other ABI mismatches.

    -

    Do not call a function through a type whose language linkage does not match the language linkage of the called function's definition. This restriction applies both to functions called within a C++ program as well as function pointers used to make a function call from outside of the C++ program.

    -

    However, many compilers fail to integrate language linkage into the function's type, despite the normative requirement to do so in the C++ Standard. For instance, GCC 6.1.0, Clang 3.9, and Microsoft Visual Studio 2015 all consider the following code snippet to be ill-formed due to a redefinition of f() rather than a well-formed overload of f().

    - typedef void (*cpp_func)(void); +

    + When calling a function, it is + + undefined behavior + + if the language linkage of the function type used in the call does not match the language linkage of the function definition.ย For instance, a mismatch in language linkage specification may corrupt the call stack due to calling conventions or other ABI mismatches. +

    +

    + Do not call a function through a type whose language linkage does not match the language linkage of the called function's definition. This restriction applies both to functions called within a C++ program as well as function pointers used to make a function call from outside of the C++ program. +

    +

    + However, many compilers fail to integrate language linkage into theย function's type, despite the normative requirement to do so in the C++ย Standard.ย For instance, + + GCC + + 6.1.0, + + Clang + + 3.9, and + + Microsoft Visual Studio + + 2015 all consider the following code snippet to be + + ill-formed + + due to a redefinition of + + f() + + rather than a + + well-formed + + overloadย of + + f() + + . +

    + + typedef void (*cpp_func)(void); extern "C" typedef void (*c_func)(void); void f(cpp_func fp) {} -void f(c_func fp) {} -

    Some compilers conform to the C++ Standard, but only in their strictest conformance mode, such as EDG 4.11. This implementation divergence from the C++ Standard is a matter of practical design trade-offs. Compilers are required to support only the "C" and "C++" language linkages, and interoperability between these two languages often does not require significant code generation differences beyond the mangling of function types for most common architectures such as x86, x86-64, and ARM. There are extant Standard Template Library implementations for which language linkage specifications being correctly implemented as part of the function type would break existing code on common platforms where the language linkage has no effect on the runtime implementation of a function call.

    -

    It is acceptable to call a function with a mismatched language linkage when the combination of language linkage specifications, runtime platform, and compiler implementation result in no effect on runtime behavior of the function call. For instance, the following code is permissible when compiled with Microsoft Visual Studio 2015 for x86, despite the lambda function call operator implicitly converting to a function pointer type with C++ language linkage, while qsort() expects a function pointer with C language linkage.

    - #include <cstdlib> +void f(c_func fp) {} + +

    + Some compilers conform to the C++ Standard, but only in their strictest conformance mode, such as EDG 4.11. This implementation divergence from the C++ Standard is a matter of practical design trade-offs. Compilers are required to support onlyย the + + "C" + + and + + "C++" + + language linkages, and interoperability between these two languages often does not require significant code generation differences beyond the mangling of function types for most common architectures such as x86, x86-64, and ARM. There are extant Standard Template Library implementations for which language linkage specifications being correctly implemented as part of the function type would break existing code on common platforms where the language linkage has no effect on the runtime implementation of a function call. +

    +

    + It is acceptable to call a function with a mismatched language linkageย when theย combination ofย language linkage specifications, runtime platform, and compiler implementation result in no effect on runtime behavior of the function call. For instance, the following code is permissible when compiled with Microsoft Visual Studio 2015 for x86, despite the lambda function call operator implicitly converting to a function pointer type with C++ language linkage, while + + qsort() + + expects a function pointer with C language linkage. +

    + + #include <cstdlib> void f(int *int_list, size_t count) { std::qsort(int_list, count, sizeof(int), @@ -25,32 +111,74 @@ void f(int *int_list, size_t count) { reinterpret_cast<const int *>(rhs); }); } - +
    -

    In this noncompliant code example, the call_java_fn_ptr() function expects to receive a function pointer with "java" language linkage because that function pointer will be used by a Java interpreter to call back into the C++ code. However, the function is given a pointer with "C++" language linkage instead, resulting in undefined behavior when the interpreter attempts to call the function pointer. This code should be ill-formed because the type of callback_func() is different than the type java_callback. However, due to common implementation divergence from the C++ Standard, some compilers may incorrectly accept this code without issuing a diagnostic.

    - extern "java" typedef void (*java_callback)(int); - +

    + In this noncompliant code example, the + + call_java_fn_ptr() + + function expects to receive a function pointer with + + "java" + + language linkage because that function pointer will be used by a Java interpreter to call back into the C++ code. However, the function is given a pointer with + + "C++" + + language linkage instead, resulting in undefined behavior when the interpreter attempts to call the function pointer. This code should be ill-formed because the type of + + callback_func() + + is different than the type + + java_callback. However, + + due to common implementation divergence from the C++ Standard, some compilers may incorrectly accept this code without issuing a diagnostic. +

    + + extern "java" typedef void (*java_callback)(int); +ย  extern void call_java_fn_ptr(java_callback callback); void callback_func(int); - +ย  void f() { call_java_fn_ptr(callback_func); -} +} +
    -

    In this compliant solution, the callback_func() function is given "java" language linkage to match the language linkage for java_callback.

    - extern "java" typedef void (*java_callback)(int); +

    + In this compliant solution, the + + callback_func() + + function is given + + "java" + + language linkage to match the language linkage for + + java_callback + + . +

    + + extern "java" typedef void (*java_callback)(int); extern void call_java_fn_ptr(java_callback callback); extern "java" void callback_func(int); void f() { call_java_fn_ptr(callback_func); -} +} +
    -

    Mismatched language linkage specifications generally do not create exploitable security vulnerabilities between the C and C++ language linkages. However, other language linkages exist where the undefined behavior is more likely to result in abnormal program execution, including exploitable vulnerabilities.

    +

    + Mismatched language linkage specifications generally do not create exploitable security vulnerabilities between the C and C++ language linkages. However, other language linkages exist where the undefined behavior is more likely to result in abnormal program execution, including exploitable vulnerabilities. +

    Item 94, "Avoid Casting Away - const + + const + "
    @@ -87,10 +215,14 @@ void f() { Medium @@ -123,7 +255,9 @@ void f() { 2021.2 @@ -138,12 +272,36 @@ void f() { 2021.4 @@ -158,7 +316,9 @@ void f() { 2021.2 @@ -183,7 +345,17 @@ void f() {
    - P2 + + P2 + - L3 + + L3 +
    - C++3033, C++3038 + + C++3033, C++3038 + - PORTING.CAST.PTR - PORTING.CAST.PTR.FLTPNT - PORTING.CAST.PTR.SIZE - PORTING.CAST.SIZE - MISRA.CAST.PTR.UNRELATED - MISRA.CAST.PTR_TO_INT + + + PORTING.CAST.PTR + + + + + PORTING.CAST.PTR.FLTPNT + + + + + PORTING.CAST.PTR.SIZE + + + + + PORTING.CAST.SIZE + + + + + MISRA.CAST.PTR.UNRELATED + + + + + MISRA.CAST.PTR_TO_INT + + - CERT_CPP-EXP56-a + + CERT_CPP-EXP56-a + Do not call a function with a mismatched language linkage @@ -174,7 +334,9 @@ void f() { 4.4 - 3033. 3038 + + 3033. 3038 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass-standard.qhelp b/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass-standard.qhelp index a8510f29ba..4d0b452eb5 100644 --- a/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass-standard.qhelp +++ b/cpp/cert/src/rules/EXP57-CPP/CastOfPointerToIncompleteClass-standard.qhelp @@ -1,28 +1,117 @@
    -

    Referring to objects of incomplete class type, also known as forward declarations, is a common practice. One such common usage is with the "pimpl idiom" [Sutter 00] whereby an opaque pointer is used to hide implementation details from a public-facing API. However, attempting to delete a pointer to an object of incomplete class type can lead to undefined behavior. The C++ Standard, [expr.delete], paragraph 5 [ISO/IEC 14882-2014], states the following:

    +

    + Referring to objects of incomplete class type, also known as + + forward declarations + + , is a common practice. One such common usage is with the "pimpl idiom" [ + + Sutter 00 + + ] whereby an opaque pointer is used to hide implementation details from a public-facing API. However, attempting to delete a pointer to an object of incomplete class type can lead to + + undefined behavior + + .ย The C++ Standard,ย [expr.delete], paragraph 5 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.

    +

    + If the object being deleted has incomplete class type at the point of deletion and the complete class has aย non-trivial destructor or a deallocation function, the behavior is undefined. +

    -

    Do not attempt to delete a pointer to an object of incomplete type. Although it is well-formed if the class has no nontrivial destructor and no associated deallocation function, it would become undefined behavior were a nontrivial destructor or deallocation function added later. It would be possible to check for a nontrivial destructor at compile time using a static_assert and the std::is_trivially_destructible type trait, but no such type trait exists to test for the presence of a deallocation function.

    -

    Pointer downcasting to a pointer of incomplete class type has similar caveats. Pointer upcasting (casting from a more derived type to a less derived type) is a standard implicit conversion operation. C++ allows static_cast to perform the inverse operation, pointer downcasting, via [expr.static.cast], paragraph 7. However, when the pointed-to type is incomplete, the compiler is unable to make any class offset adjustments that may be required in the presence of multiple inheritance, resulting in a pointer that cannot be validly dereferenced.

    -

    reinterpret_cast of a pointer type is defined by [expr.reinterpret.cast], paragraph 7, as being static_cast<cv T *>(static_cast<cv void *>(PtrValue)), meaning that reinterpret_cast is simply a sequence of static_cast operations. C-style casts of a pointer to an incomplete object type are defined as using either static_cast or reinterpret_cast (it is unspecified which is picked) in [expr.cast], paragraph 5.

    -

    Do not attempt to cast through a pointer to an object of incomplete type. The cast operation itself is well-formed, but dereferencing the resulting pointer may result in undefined behavior if the downcast is unable to adjust for multiple inheritance.

    +

    + Do not attempt to delete a pointer to an object of + + incomplete type + + . Although it is well-formed if the class has no nontrivial destructor and no associated deallocation function, it would become undefined behavior were a nontrivial destructor or deallocation function added later. It would be possible to check for a nontrivial destructor at compile time using a + + static_assert + + and the + + std::is_trivially_destructible + + type trait, but no such type trait exists to test for the presence of a deallocation function. +

    +

    + Pointer downcasting to a pointer of incomplete class type has similar caveats. Pointer upcasting (casting from a more derived type to a less derived type) is a standard implicit conversion operation. C++ allows + + static_cast + + toย perform the inverse operation, pointer downcasting, viaย [expr.static.cast], paragraph 7. However, when the pointed-to type is incomplete, the compiler is unable to make any class offset adjustments that may be required in the presence of multiple inheritance, resulting in a pointer that cannot be validly dereferenced. +

    +

    + + reinterpret_cast + + of a pointer type is defined byย [expr.reinterpret.cast], paragraph 7, as being + + static_cast<cv T *>(static_cast<cv void *>(PtrValue)) + + , meaning that + + reinterpret_cast + + is simply a sequence of + + static_cast + + operations. C-style casts of a pointer to anย incomplete object type are defined as using either + + static_cast + + or + + reinterpret_cast + + (it is unspecified which is picked) inย [expr.cast], paragraph 5. +

    +

    + Do not attempt to cast through a pointer to an object of incomplete type. The cast operation itself is well-formed, but dereferencing the resulting pointer may result in undefined behavior if the downcast is unable to adjust for multiple inheritance. +

    -

    In this noncompliant code example, a class attempts to implement the pimpl idiom but deletes a pointer to an incomplete class type, resulting in undefined behavior if Body has a nontrivial destructor.

    - class Handle { +

    + In this noncompliant code example, a class attempts to implement the pimpl idiom but deletes a pointer to an incomplete class type, resulting in + + undefined behavior + + if + + Body + + has a nontrivial destructor. +

    + + class Handle { class Body *impl; // Declaration of a pointer to an incomplete class public: ~Handle() { delete impl; } // Deletion of pointer to an incomplete class // ... }; - +
    -

    In this compliant solution, the deletion of impl is moved to a part of the code where Body is defined.

    - class Handle { +

    + In this compliant solution, the deletion of + + impl + + is moved to a part of the code where + + Body + + is defined. +

    + + class Handle { class Body *impl; // Declaration of a pointer to an incomplete class public: ~Handle(); @@ -31,33 +120,85 @@ public: // Elsewhere class Body { /* ... */ }; - +ย  Handle::~Handle() { delete impl; -} +} +
    -

    In this compliant solution, a std::shared_ptr is used to own the memory to impl. A std::shared_ptr is capable of referring to an incomplete type, but a std::unique_ptr is not.

    - #include <memory> - +

    + In this compliant solution, a + + std::shared_ptr + + is used to own the memory to + + impl + + .ย A + + std::shared_ptr + + is capable of referring to an incomplete type, but a + + std::unique_ptr + + is not. +

    + + #include <memory> +ย  class Handle { std::shared_ptr<class Body> impl; public: Handle(); ~Handle() {} // ... -}; +}; +
    -

    Pointer downcasting (casting a pointer to a base class into a pointer to a derived class) may require adjusting the address of the pointer by a fixed amount that can be determined only when the layout of the class inheritance structure is known. In this noncompliant code example, f() retrieves a polymorphic pointer of complete type B from get_d(). That pointer is then cast to a pointer of incomplete type D before being passed to g(). Casting to a pointer to the derived class may fail to properly adjust the resulting pointer, causing undefined behavior when the pointer is dereferenced by calling d->do_something().

    - // File1.h +

    + Pointer downcasting (casting a pointer to a base class into a pointer to a derived class) may require adjusting the address of the pointer by a fixed amount that can be determined only when the layout of the class inheritance structure is known. In this noncompliant code example, + + f() + + retrieves a polymorphic pointer of complete type + + B + + from + + get_d() + + . That pointer is then cast to a pointer of incomplete type + + D + + before being passed to + + g() + + .ย Casting to a pointer to the derived class may fail to properly adjust the resulting pointer, causing + + undefined behavior + + when the pointer is dereferenced by calling + + d->do_something() + + . +

    + + // File1.h class B { protected: double d; public: B() : d(1.0) {} }; - +ย  // File2.h void g(class D *); class B *get_d(); // Returns a pointer to a D object @@ -70,7 +211,7 @@ void f() { B *v = get_d(); g(reinterpret_cast<class D *>(v)); } - +ย  // File2.cpp #include "File2.h" #include "File1.h" @@ -97,15 +238,59 @@ void g(D *d) { B *get_d() { return new D; } - -

    Implementation Details

    -

    When compiled with ClangBB. Definitions#clang3.8 and the function f() is executed, the noncompliant code example prints the following.

    - f: 1.89367e-40, d: 5.27183e-315, s: 0 -

    Similarly, unexpected values are printed when the example is run in Microsoft Visual Studio 2015 and GCC 6.1.0.

    +
    +

    + + Implementation Details + +

    +

    + When compiled with + + Clang + + + BB. Definitions#clang + + 3.8 and the function + + f() + + is executed, the noncompliant code example prints the following. +

    + + f: 1.89367e-40, d: 5.27183e-315, s: 0 + +

    + Similarly, unexpected values areย printed when the example is run in + + Microsoft Visual Studio + + 2015 and + + GCC + + 6.1.0. +

    -

    This compliant solution assumes that the intent is to hide implementation details by using incomplete class types. Instead of requiring a D * to be passed to g(), it expects a B * type.

    - // File1.h -- contents identical. +

    + This compliant solution assumes that the intent is to hide implementation details by using incomplete class types. Instead of requiring a + + D * + + to be passed to + + g() + + , it expects a + + B * + + type. +

    + + // File1.h -- contents identical. // File2.h void g(class B *); // Accepts a B object, expects a D object class B *get_d(); // Returns a pointer to a D object @@ -132,10 +317,13 @@ void g(B *d) { B *get_d() { return new D; -} +} +
    -

    Casting pointers or references to incomplete classes can result in bad addresses. Deleting a pointer to an incomplete class results in undefined behavior if the class has a nontrivial destructor. Doing so can cause program termination, a runtime signal, or resource leaks.

    +

    + Casting pointers or references to incomplete classes can result in bad addresses. Deleting a pointer to an incomplete class results in undefined behavior if the class has a nontrivial destructor. Doing so can cause program termination, a runtime signal, or resource leaks. +

    @@ -172,10 +360,14 @@ B *get_d() { Medium @@ -208,7 +400,9 @@ B *get_d() { 20.10 @@ -223,7 +417,9 @@ B *get_d() { 6.5 @@ -251,10 +449,12 @@ B *get_d() { @@ -285,7 +487,11 @@ B *get_d() { 2021.4 @@ -299,8 +505,11 @@ B *get_d() { @@ -375,7 +590,17 @@ B *get_d() {
    - P4 + + P4 + - L3 + + L3 +
    - delete-with-incomplete-type + + delete-with-incomplete-type + - DELETE_VOID + + DELETE_VOID + Fully implemented @@ -239,7 +435,9 @@ B *get_d() { 3.9 - -Wdelete-incomplete + + -Wdelete-incomplete + - 6.2p0 + 6.1p0 - LANG.CAST.PC.INC + + LANG.CAST.PC.INC + Conversion: pointer to incomplete @@ -270,7 +470,9 @@ B *get_d() { 2021.2 - C++3112 + + C++3112 + - CERT.EXPR.DELETE_PTR.INCOMPLETE_TYPE + + + CERT.EXPR.DELETE_PTR.INCOMPLETE_TYPE + + - 169 S, 554 S - + + 169 S, 554 S + + + Enhanced Enforcement @@ -316,8 +525,12 @@ B *get_d() { 2021.2 - CERT_CPP-EXP57-a - CERT_CPP-EXP57-b + + CERT_CPP-EXP57-a + + + CERT_CPP-EXP57-b + Do not delete objects with incomplete class at the point of deletion @@ -366,7 +579,9 @@ B *get_d() { 20.10 - delete-with-incomplete-type + + delete-with-incomplete-type +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass-standard.qhelp b/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass-standard.qhelp index a8510f29ba..4d0b452eb5 100644 --- a/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass-standard.qhelp +++ b/cpp/cert/src/rules/EXP57-CPP/DeletingPointerToIncompleteClass-standard.qhelp @@ -1,28 +1,117 @@
    -

    Referring to objects of incomplete class type, also known as forward declarations, is a common practice. One such common usage is with the "pimpl idiom" [Sutter 00] whereby an opaque pointer is used to hide implementation details from a public-facing API. However, attempting to delete a pointer to an object of incomplete class type can lead to undefined behavior. The C++ Standard, [expr.delete], paragraph 5 [ISO/IEC 14882-2014], states the following:

    +

    + Referring to objects of incomplete class type, also known as + + forward declarations + + , is a common practice. One such common usage is with the "pimpl idiom" [ + + Sutter 00 + + ] whereby an opaque pointer is used to hide implementation details from a public-facing API. However, attempting to delete a pointer to an object of incomplete class type can lead to + + undefined behavior + + .ย The C++ Standard,ย [expr.delete], paragraph 5 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.

    +

    + If the object being deleted has incomplete class type at the point of deletion and the complete class has aย non-trivial destructor or a deallocation function, the behavior is undefined. +

    -

    Do not attempt to delete a pointer to an object of incomplete type. Although it is well-formed if the class has no nontrivial destructor and no associated deallocation function, it would become undefined behavior were a nontrivial destructor or deallocation function added later. It would be possible to check for a nontrivial destructor at compile time using a static_assert and the std::is_trivially_destructible type trait, but no such type trait exists to test for the presence of a deallocation function.

    -

    Pointer downcasting to a pointer of incomplete class type has similar caveats. Pointer upcasting (casting from a more derived type to a less derived type) is a standard implicit conversion operation. C++ allows static_cast to perform the inverse operation, pointer downcasting, via [expr.static.cast], paragraph 7. However, when the pointed-to type is incomplete, the compiler is unable to make any class offset adjustments that may be required in the presence of multiple inheritance, resulting in a pointer that cannot be validly dereferenced.

    -

    reinterpret_cast of a pointer type is defined by [expr.reinterpret.cast], paragraph 7, as being static_cast<cv T *>(static_cast<cv void *>(PtrValue)), meaning that reinterpret_cast is simply a sequence of static_cast operations. C-style casts of a pointer to an incomplete object type are defined as using either static_cast or reinterpret_cast (it is unspecified which is picked) in [expr.cast], paragraph 5.

    -

    Do not attempt to cast through a pointer to an object of incomplete type. The cast operation itself is well-formed, but dereferencing the resulting pointer may result in undefined behavior if the downcast is unable to adjust for multiple inheritance.

    +

    + Do not attempt to delete a pointer to an object of + + incomplete type + + . Although it is well-formed if the class has no nontrivial destructor and no associated deallocation function, it would become undefined behavior were a nontrivial destructor or deallocation function added later. It would be possible to check for a nontrivial destructor at compile time using a + + static_assert + + and the + + std::is_trivially_destructible + + type trait, but no such type trait exists to test for the presence of a deallocation function. +

    +

    + Pointer downcasting to a pointer of incomplete class type has similar caveats. Pointer upcasting (casting from a more derived type to a less derived type) is a standard implicit conversion operation. C++ allows + + static_cast + + toย perform the inverse operation, pointer downcasting, viaย [expr.static.cast], paragraph 7. However, when the pointed-to type is incomplete, the compiler is unable to make any class offset adjustments that may be required in the presence of multiple inheritance, resulting in a pointer that cannot be validly dereferenced. +

    +

    + + reinterpret_cast + + of a pointer type is defined byย [expr.reinterpret.cast], paragraph 7, as being + + static_cast<cv T *>(static_cast<cv void *>(PtrValue)) + + , meaning that + + reinterpret_cast + + is simply a sequence of + + static_cast + + operations. C-style casts of a pointer to anย incomplete object type are defined as using either + + static_cast + + or + + reinterpret_cast + + (it is unspecified which is picked) inย [expr.cast], paragraph 5. +

    +

    + Do not attempt to cast through a pointer to an object of incomplete type. The cast operation itself is well-formed, but dereferencing the resulting pointer may result in undefined behavior if the downcast is unable to adjust for multiple inheritance. +

    -

    In this noncompliant code example, a class attempts to implement the pimpl idiom but deletes a pointer to an incomplete class type, resulting in undefined behavior if Body has a nontrivial destructor.

    - class Handle { +

    + In this noncompliant code example, a class attempts to implement the pimpl idiom but deletes a pointer to an incomplete class type, resulting in + + undefined behavior + + if + + Body + + has a nontrivial destructor. +

    + + class Handle { class Body *impl; // Declaration of a pointer to an incomplete class public: ~Handle() { delete impl; } // Deletion of pointer to an incomplete class // ... }; - +
    -

    In this compliant solution, the deletion of impl is moved to a part of the code where Body is defined.

    - class Handle { +

    + In this compliant solution, the deletion of + + impl + + is moved to a part of the code where + + Body + + is defined. +

    + + class Handle { class Body *impl; // Declaration of a pointer to an incomplete class public: ~Handle(); @@ -31,33 +120,85 @@ public: // Elsewhere class Body { /* ... */ }; - +ย  Handle::~Handle() { delete impl; -} +} +
    -

    In this compliant solution, a std::shared_ptr is used to own the memory to impl. A std::shared_ptr is capable of referring to an incomplete type, but a std::unique_ptr is not.

    - #include <memory> - +

    + In this compliant solution, a + + std::shared_ptr + + is used to own the memory to + + impl + + .ย A + + std::shared_ptr + + is capable of referring to an incomplete type, but a + + std::unique_ptr + + is not. +

    + + #include <memory> +ย  class Handle { std::shared_ptr<class Body> impl; public: Handle(); ~Handle() {} // ... -}; +}; +
    -

    Pointer downcasting (casting a pointer to a base class into a pointer to a derived class) may require adjusting the address of the pointer by a fixed amount that can be determined only when the layout of the class inheritance structure is known. In this noncompliant code example, f() retrieves a polymorphic pointer of complete type B from get_d(). That pointer is then cast to a pointer of incomplete type D before being passed to g(). Casting to a pointer to the derived class may fail to properly adjust the resulting pointer, causing undefined behavior when the pointer is dereferenced by calling d->do_something().

    - // File1.h +

    + Pointer downcasting (casting a pointer to a base class into a pointer to a derived class) may require adjusting the address of the pointer by a fixed amount that can be determined only when the layout of the class inheritance structure is known. In this noncompliant code example, + + f() + + retrieves a polymorphic pointer of complete type + + B + + from + + get_d() + + . That pointer is then cast to a pointer of incomplete type + + D + + before being passed to + + g() + + .ย Casting to a pointer to the derived class may fail to properly adjust the resulting pointer, causing + + undefined behavior + + when the pointer is dereferenced by calling + + d->do_something() + + . +

    + + // File1.h class B { protected: double d; public: B() : d(1.0) {} }; - +ย  // File2.h void g(class D *); class B *get_d(); // Returns a pointer to a D object @@ -70,7 +211,7 @@ void f() { B *v = get_d(); g(reinterpret_cast<class D *>(v)); } - +ย  // File2.cpp #include "File2.h" #include "File1.h" @@ -97,15 +238,59 @@ void g(D *d) { B *get_d() { return new D; } - -

    Implementation Details

    -

    When compiled with ClangBB. Definitions#clang3.8 and the function f() is executed, the noncompliant code example prints the following.

    - f: 1.89367e-40, d: 5.27183e-315, s: 0 -

    Similarly, unexpected values are printed when the example is run in Microsoft Visual Studio 2015 and GCC 6.1.0.

    +
    +

    + + Implementation Details + +

    +

    + When compiled with + + Clang + + + BB. Definitions#clang + + 3.8 and the function + + f() + + is executed, the noncompliant code example prints the following. +

    + + f: 1.89367e-40, d: 5.27183e-315, s: 0 + +

    + Similarly, unexpected values areย printed when the example is run in + + Microsoft Visual Studio + + 2015 and + + GCC + + 6.1.0. +

    -

    This compliant solution assumes that the intent is to hide implementation details by using incomplete class types. Instead of requiring a D * to be passed to g(), it expects a B * type.

    - // File1.h -- contents identical. +

    + This compliant solution assumes that the intent is to hide implementation details by using incomplete class types. Instead of requiring a + + D * + + to be passed to + + g() + + , it expects a + + B * + + type. +

    + + // File1.h -- contents identical. // File2.h void g(class B *); // Accepts a B object, expects a D object class B *get_d(); // Returns a pointer to a D object @@ -132,10 +317,13 @@ void g(B *d) { B *get_d() { return new D; -} +} +
    -

    Casting pointers or references to incomplete classes can result in bad addresses. Deleting a pointer to an incomplete class results in undefined behavior if the class has a nontrivial destructor. Doing so can cause program termination, a runtime signal, or resource leaks.

    +

    + Casting pointers or references to incomplete classes can result in bad addresses. Deleting a pointer to an incomplete class results in undefined behavior if the class has a nontrivial destructor. Doing so can cause program termination, a runtime signal, or resource leaks. +

    @@ -172,10 +360,14 @@ B *get_d() { Medium @@ -208,7 +400,9 @@ B *get_d() { 20.10 @@ -223,7 +417,9 @@ B *get_d() { 6.5 @@ -251,10 +449,12 @@ B *get_d() { @@ -285,7 +487,11 @@ B *get_d() { 2021.4 @@ -299,8 +505,11 @@ B *get_d() { @@ -375,7 +590,17 @@ B *get_d() {
    - P4 + + P4 + - L3 + + L3 +
    - delete-with-incomplete-type + + delete-with-incomplete-type + - DELETE_VOID + + DELETE_VOID + Fully implemented @@ -239,7 +435,9 @@ B *get_d() { 3.9 - -Wdelete-incomplete + + -Wdelete-incomplete + - 6.2p0 + 6.1p0 - LANG.CAST.PC.INC + + LANG.CAST.PC.INC + Conversion: pointer to incomplete @@ -270,7 +470,9 @@ B *get_d() { 2021.2 - C++3112 + + C++3112 + - CERT.EXPR.DELETE_PTR.INCOMPLETE_TYPE + + + CERT.EXPR.DELETE_PTR.INCOMPLETE_TYPE + + - 169 S, 554 S - + + 169 S, 554 S + + + Enhanced Enforcement @@ -316,8 +525,12 @@ B *get_d() { 2021.2 - CERT_CPP-EXP57-a - CERT_CPP-EXP57-b + + CERT_CPP-EXP57-a + + + CERT_CPP-EXP57-b + Do not delete objects with incomplete class at the point of deletion @@ -366,7 +579,9 @@ B *get_d() { 20.10 - delete-with-incomplete-type + + delete-with-incomplete-type +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart-standard.qhelp b/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart-standard.qhelp index 3d374d8649..19bc5a0141 100644 --- a/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart-standard.qhelp +++ b/cpp/cert/src/rules/EXP58-CPP/PassNonTrivialObjectToVaStart-standard.qhelp @@ -1,35 +1,151 @@
    -

    While rule DCL50-CPP. Do not define a C-style variadic function forbids creation of such functions, they may still be defined when that function has external, C language linkage. Under these circumstances, care must be taken when invoking the va_start() macro. The C-standard library macro va_start() imposes several semantic restrictions on the type of the value of its second parameter. The C Standard, subclause 7.16.1.4, paragraph 4 [ISO/IEC 9899:2011], states the following:

    +

    + While rule + + DCL50-CPP. Do not define a C-style variadic function + + forbids creation of such functions, they may still be definedย when that function has external, C language linkage. Under these circumstances, care must be taken when invoking the + + va_start() + + macro.ย The C-standard library macro + + va_start() + + imposes several semantic restrictions on the type of the value of its second parameter. The C Standard, subclause 7.16.1.4, paragraph 4 [ + + ISO/IEC 9899:2011 + + ], states the following: +

    -

    The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the ...). If the parameter parmN is declared with the register storage class, with a function or array type, or with a type that is not compatible with the type that results after application of the default argument promotions, the behavior is undefined.

    +

    + The parameter + + parmN + + is the identifier of the rightmost parameter in the variableย parameter list in the function definition (the one just before the + + ... + + ). If the parameter + + parmN + + is declared with the + + register + + storage class, with a function or array type, orย with a type that is not compatible with the type that results after application of the defaultย argument promotions, the behavior is undefined. +

    -

    These restrictions are superseded by the C++ Standard, [support.runtime], paragraph 3 [ISO/IEC 14882-2014], which states the following:

    +

    + These restrictions are superseded by the C++ Standard,ย [support.runtime], paragraph 3 + [ + + ISO/IEC 14882-2014 + + ] + , which states the following: +

    -

    The restrictions that ISO C places on the second parameter to the va_start() macro in header <stdarg.h> are different in this International Standard. The parameter parmN is the identifier of the rightmost parameter in the variable parameter list of the function definition (the one just before the ...). If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

    +

    + The restrictions that ISO C places on the second parameter to the + + va_start() + + macro in header + + <stdarg.h> + + are different in this International Standard. The parameter + + parmN + + is the identifier of the rightmost parameterย in the variable parameter list of the function definition (the one just before the + + ... + + ).ย If the parameter + + parmN + + is of a reference type, or of a type that is not compatible with the type that results when passing anย argument for which there is no parameter, the behavior is undefined. +

    -

    The primary differences between the semantic requirements are as follows:

    +

    + The primary differences between the semantic requirements are as follows: +

      -
    • You must not pass a reference as the second argument to va_start().
    • -
    • Passing an object of a class type that has a nontrivial copy constructor, nontrivial move constructor, or nontrivial destructor as the second argument to va_start is conditionally supported with implementation-defined semantics ([expr.call] paragraph 7).
    • -
    • You may pass a parameter declared with the register keyword ([dcl.stc] paragraph 3) or a parameter with a function type.
    • +
    • + You must not pass a reference as the second argument to + + va_start() + + . +
    • +
    • + Passing an object of a class type that has a nontrivial copy constructor, nontrivial move constructor, or nontrivial destructor as the second argument to + + va_start + + is conditionally supported with implementation-defined semantics ([expr.call] paragraph 7). +
    • +
    • + You may pass a parameter declared with the + + register + + keyword ([dcl.stc] paragraph 3) or a parameter with a function type. +
    -

    Passing an object of array type still produces undefined behavior in C++ because an array type as a function parameter requires the use of a reference, which is prohibited. Additionally, passing an object of a type that undergoes default argument promotions still produces undefined behavior in C++.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the object passed to va_start() will undergo a default argument promotion, which results in undefined behavior.

    - #include <cstdarg> +

    + Passing an object of array type still produces + + undefined behavior + + in C++ because an array type as a function parameter requires theย use of a reference, which is prohibited. Additionally, passing an object of a type that undergoes default argument promotions still produces undefined behavior in C++. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the object passed to + + va_start() + + will undergo a default argument promotion, which results in undefined behavior. +

    + + #include <cstdarg> extern "C" void f(float a, ...) { va_list list; va_start(list, a); // ... va_end(list); -} +} +
    -

    In this compliant solution, f() accepts a double instead of a float.

    - #include <cstdarg> +

    + In this compliant solution, + + f() + + accepts a + + double + + instead of a + + float. + +

    + + #include <cstdarg> extern "C" void f(double a, ...) { va_list list; @@ -37,11 +153,17 @@ extern "C" void f(double a, ...) { // ... va_end(list); } - +
    -

    In this noncompliant code example, a reference type is passed as the second argument to va_start().

    - #include <cstdarg> +

    + In this noncompliant code example, a reference type is passed as the second argument to + + va_start(). + +

    + + #include <cstdarg> #include <iostream> extern "C" void f(int &a, ...) { @@ -52,11 +174,19 @@ extern "C" void f(int &a, ...) { a = 100; // Assign something to a for the caller } va_end(list); -} +} +
    -

    Instead of passing a reference type to f(), this compliant solution passes a pointer type.

    - #include <cstdarg> +

    + Instead of passing a reference type to + + f() + + , this compliant solution passes a pointer type. +

    + + #include <cstdarg> #include <iostream> extern "C" void f(int *a, ...) { @@ -68,11 +198,26 @@ extern "C" void f(int *a, ...) { } va_end(list); } - +
    -

    In this noncompliant code example, a class with a nontrivial copy constructor (std::string) is passed as the second argument to va_start(), which is conditionally supported depending on the implementation.

    - #include <cstdarg> +

    + In this noncompliant code example, a class with a nontrivial copy constructor ( + + std::string + + )ย is passed as the second argument to + + va_start() + + , which is conditionally supported depending on the + + implementation + + . +

    + + #include <cstdarg> #include <iostream> #include <string> @@ -81,11 +226,23 @@ extern "C" void f(std::string s, ...) { va_start(list, s); std::cout << s << ", " << va_arg(list, int); va_end(list); -} +} +
    -

    This compliant solution passes a const char * instead of a std::string, which has well-defined behavior on all implementations.

    - #include <cstdarg> +

    + This compliant solution passes a + + const char * + + instead of a + + std::string + + , which has well-defined behavior on all implementations. +

    + + #include <cstdarg> #include <iostream> extern "C" void f(const char *s, ...) { @@ -93,10 +250,25 @@ extern "C" void f(const char *s, ...) { va_start(list, s); std::cout << (s ? s : "") << ", " << va_arg(list, int); va_end(list); -} +} +
    -

    Passing an object of an unsupported type as the second argument to va_start() can result in undefined behavior that might be exploited to cause data integrity violations.

    +

    + Passing an object of an unsupported type as the second argument to + + va_start() + + can result in + + undefined behavior + + that might be + + exploited + + to cause data integrity violations. +

    @@ -133,10 +305,14 @@ extern "C" void f(const char *s, ...) { Medium @@ -169,7 +345,9 @@ extern "C" void f(const char *s, ...) { 3.9 @@ -204,7 +384,9 @@ extern "C" void f(const char *s, ...) { 2021.2
    - P4 + + P4 + - L3 + + L3 +
    - -Wvarargs + + -Wvarargs + Does not catch the violation in the third noncompliant code example (it is conditionally supported by @@ -189,7 +367,9 @@ extern "C" void f(const char *s, ...) { 2021.2 - C++3852, C++3853 + + C++3852, C++3853 + - CERT_CPP-EXP58-a + + CERT_CPP-EXP58-a + Use macros for variable arguments correctly @@ -232,7 +414,17 @@ extern "C" void f(const char *s, ...) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -265,7 +457,9 @@ extern "C" void f(const char *s, ...) { diff --git a/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart-standard.qhelp b/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart-standard.qhelp index 3d374d8649..19bc5a0141 100644 --- a/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart-standard.qhelp +++ b/cpp/cert/src/rules/EXP58-CPP/PassPromotablePrimitiveTypeToVaStart-standard.qhelp @@ -1,35 +1,151 @@
    -

    While rule DCL50-CPP. Do not define a C-style variadic function forbids creation of such functions, they may still be defined when that function has external, C language linkage. Under these circumstances, care must be taken when invoking the va_start() macro. The C-standard library macro va_start() imposes several semantic restrictions on the type of the value of its second parameter. The C Standard, subclause 7.16.1.4, paragraph 4 [ISO/IEC 9899:2011], states the following:

    +

    + While rule + + DCL50-CPP. Do not define a C-style variadic function + + forbids creation of such functions, they may still be definedย when that function has external, C language linkage. Under these circumstances, care must be taken when invoking the + + va_start() + + macro.ย The C-standard library macro + + va_start() + + imposes several semantic restrictions on the type of the value of its second parameter. The C Standard, subclause 7.16.1.4, paragraph 4 [ + + ISO/IEC 9899:2011 + + ], states the following: +

    -

    The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the ...). If the parameter parmN is declared with the register storage class, with a function or array type, or with a type that is not compatible with the type that results after application of the default argument promotions, the behavior is undefined.

    +

    + The parameter + + parmN + + is the identifier of the rightmost parameter in the variableย parameter list in the function definition (the one just before the + + ... + + ). If the parameter + + parmN + + is declared with the + + register + + storage class, with a function or array type, orย with a type that is not compatible with the type that results after application of the defaultย argument promotions, the behavior is undefined. +

    -

    These restrictions are superseded by the C++ Standard, [support.runtime], paragraph 3 [ISO/IEC 14882-2014], which states the following:

    +

    + These restrictions are superseded by the C++ Standard,ย [support.runtime], paragraph 3 + [ + + ISO/IEC 14882-2014 + + ] + , which states the following: +

    -

    The restrictions that ISO C places on the second parameter to the va_start() macro in header <stdarg.h> are different in this International Standard. The parameter parmN is the identifier of the rightmost parameter in the variable parameter list of the function definition (the one just before the ...). If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

    +

    + The restrictions that ISO C places on the second parameter to the + + va_start() + + macro in header + + <stdarg.h> + + are different in this International Standard. The parameter + + parmN + + is the identifier of the rightmost parameterย in the variable parameter list of the function definition (the one just before the + + ... + + ).ย If the parameter + + parmN + + is of a reference type, or of a type that is not compatible with the type that results when passing anย argument for which there is no parameter, the behavior is undefined. +

    -

    The primary differences between the semantic requirements are as follows:

    +

    + The primary differences between the semantic requirements are as follows: +

      -
    • You must not pass a reference as the second argument to va_start().
    • -
    • Passing an object of a class type that has a nontrivial copy constructor, nontrivial move constructor, or nontrivial destructor as the second argument to va_start is conditionally supported with implementation-defined semantics ([expr.call] paragraph 7).
    • -
    • You may pass a parameter declared with the register keyword ([dcl.stc] paragraph 3) or a parameter with a function type.
    • +
    • + You must not pass a reference as the second argument to + + va_start() + + . +
    • +
    • + Passing an object of a class type that has a nontrivial copy constructor, nontrivial move constructor, or nontrivial destructor as the second argument to + + va_start + + is conditionally supported with implementation-defined semantics ([expr.call] paragraph 7). +
    • +
    • + You may pass a parameter declared with the + + register + + keyword ([dcl.stc] paragraph 3) or a parameter with a function type. +
    -

    Passing an object of array type still produces undefined behavior in C++ because an array type as a function parameter requires the use of a reference, which is prohibited. Additionally, passing an object of a type that undergoes default argument promotions still produces undefined behavior in C++.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the object passed to va_start() will undergo a default argument promotion, which results in undefined behavior.

    - #include <cstdarg> +

    + Passing an object of array type still produces + + undefined behavior + + in C++ because an array type as a function parameter requires theย use of a reference, which is prohibited. Additionally, passing an object of a type that undergoes default argument promotions still produces undefined behavior in C++. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the object passed to + + va_start() + + will undergo a default argument promotion, which results in undefined behavior. +

    + + #include <cstdarg> extern "C" void f(float a, ...) { va_list list; va_start(list, a); // ... va_end(list); -} +} +
    -

    In this compliant solution, f() accepts a double instead of a float.

    - #include <cstdarg> +

    + In this compliant solution, + + f() + + accepts a + + double + + instead of a + + float. + +

    + + #include <cstdarg> extern "C" void f(double a, ...) { va_list list; @@ -37,11 +153,17 @@ extern "C" void f(double a, ...) { // ... va_end(list); } - +
    -

    In this noncompliant code example, a reference type is passed as the second argument to va_start().

    - #include <cstdarg> +

    + In this noncompliant code example, a reference type is passed as the second argument to + + va_start(). + +

    + + #include <cstdarg> #include <iostream> extern "C" void f(int &a, ...) { @@ -52,11 +174,19 @@ extern "C" void f(int &a, ...) { a = 100; // Assign something to a for the caller } va_end(list); -} +} +
    -

    Instead of passing a reference type to f(), this compliant solution passes a pointer type.

    - #include <cstdarg> +

    + Instead of passing a reference type to + + f() + + , this compliant solution passes a pointer type. +

    + + #include <cstdarg> #include <iostream> extern "C" void f(int *a, ...) { @@ -68,11 +198,26 @@ extern "C" void f(int *a, ...) { } va_end(list); } - +
    -

    In this noncompliant code example, a class with a nontrivial copy constructor (std::string) is passed as the second argument to va_start(), which is conditionally supported depending on the implementation.

    - #include <cstdarg> +

    + In this noncompliant code example, a class with a nontrivial copy constructor ( + + std::string + + )ย is passed as the second argument to + + va_start() + + , which is conditionally supported depending on the + + implementation + + . +

    + + #include <cstdarg> #include <iostream> #include <string> @@ -81,11 +226,23 @@ extern "C" void f(std::string s, ...) { va_start(list, s); std::cout << s << ", " << va_arg(list, int); va_end(list); -} +} +
    -

    This compliant solution passes a const char * instead of a std::string, which has well-defined behavior on all implementations.

    - #include <cstdarg> +

    + This compliant solution passes a + + const char * + + instead of a + + std::string + + , which has well-defined behavior on all implementations. +

    + + #include <cstdarg> #include <iostream> extern "C" void f(const char *s, ...) { @@ -93,10 +250,25 @@ extern "C" void f(const char *s, ...) { va_start(list, s); std::cout << (s ? s : "") << ", " << va_arg(list, int); va_end(list); -} +} +
    -

    Passing an object of an unsupported type as the second argument to va_start() can result in undefined behavior that might be exploited to cause data integrity violations.

    +

    + Passing an object of an unsupported type as the second argument to + + va_start() + + can result in + + undefined behavior + + that might be + + exploited + + to cause data integrity violations. +

    Subclause 7.16.1.4, "The - va_start + + va_start + Macro"
    @@ -133,10 +305,14 @@ extern "C" void f(const char *s, ...) { Medium @@ -169,7 +345,9 @@ extern "C" void f(const char *s, ...) { 3.9 @@ -204,7 +384,9 @@ extern "C" void f(const char *s, ...) { 2021.2
    - P4 + + P4 + - L3 + + L3 +
    - -Wvarargs + + -Wvarargs + Does not catch the violation in the third noncompliant code example (it is conditionally supported by @@ -189,7 +367,9 @@ extern "C" void f(const char *s, ...) { 2021.2 - C++3852, C++3853 + + C++3852, C++3853 + - CERT_CPP-EXP58-a + + CERT_CPP-EXP58-a + Use macros for variable arguments correctly @@ -232,7 +414,17 @@ extern "C" void f(const char *s, ...) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -265,7 +457,9 @@ extern "C" void f(const char *s, ...) { diff --git a/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart-standard.qhelp b/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart-standard.qhelp index 3d374d8649..19bc5a0141 100644 --- a/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart-standard.qhelp +++ b/cpp/cert/src/rules/EXP58-CPP/PassReferenceTypeToVaStart-standard.qhelp @@ -1,35 +1,151 @@
    -

    While rule DCL50-CPP. Do not define a C-style variadic function forbids creation of such functions, they may still be defined when that function has external, C language linkage. Under these circumstances, care must be taken when invoking the va_start() macro. The C-standard library macro va_start() imposes several semantic restrictions on the type of the value of its second parameter. The C Standard, subclause 7.16.1.4, paragraph 4 [ISO/IEC 9899:2011], states the following:

    +

    + While rule + + DCL50-CPP. Do not define a C-style variadic function + + forbids creation of such functions, they may still be definedย when that function has external, C language linkage. Under these circumstances, care must be taken when invoking the + + va_start() + + macro.ย The C-standard library macro + + va_start() + + imposes several semantic restrictions on the type of the value of its second parameter. The C Standard, subclause 7.16.1.4, paragraph 4 [ + + ISO/IEC 9899:2011 + + ], states the following: +

    -

    The parameter parmN is the identifier of the rightmost parameter in the variable parameter list in the function definition (the one just before the ...). If the parameter parmN is declared with the register storage class, with a function or array type, or with a type that is not compatible with the type that results after application of the default argument promotions, the behavior is undefined.

    +

    + The parameter + + parmN + + is the identifier of the rightmost parameter in the variableย parameter list in the function definition (the one just before the + + ... + + ). If the parameter + + parmN + + is declared with the + + register + + storage class, with a function or array type, orย with a type that is not compatible with the type that results after application of the defaultย argument promotions, the behavior is undefined. +

    -

    These restrictions are superseded by the C++ Standard, [support.runtime], paragraph 3 [ISO/IEC 14882-2014], which states the following:

    +

    + These restrictions are superseded by the C++ Standard,ย [support.runtime], paragraph 3 + [ + + ISO/IEC 14882-2014 + + ] + , which states the following: +

    -

    The restrictions that ISO C places on the second parameter to the va_start() macro in header <stdarg.h> are different in this International Standard. The parameter parmN is the identifier of the rightmost parameter in the variable parameter list of the function definition (the one just before the ...). If the parameter parmN is of a reference type, or of a type that is not compatible with the type that results when passing an argument for which there is no parameter, the behavior is undefined.

    +

    + The restrictions that ISO C places on the second parameter to the + + va_start() + + macro in header + + <stdarg.h> + + are different in this International Standard. The parameter + + parmN + + is the identifier of the rightmost parameterย in the variable parameter list of the function definition (the one just before the + + ... + + ).ย If the parameter + + parmN + + is of a reference type, or of a type that is not compatible with the type that results when passing anย argument for which there is no parameter, the behavior is undefined. +

    -

    The primary differences between the semantic requirements are as follows:

    +

    + The primary differences between the semantic requirements are as follows: +

      -
    • You must not pass a reference as the second argument to va_start().
    • -
    • Passing an object of a class type that has a nontrivial copy constructor, nontrivial move constructor, or nontrivial destructor as the second argument to va_start is conditionally supported with implementation-defined semantics ([expr.call] paragraph 7).
    • -
    • You may pass a parameter declared with the register keyword ([dcl.stc] paragraph 3) or a parameter with a function type.
    • +
    • + You must not pass a reference as the second argument to + + va_start() + + . +
    • +
    • + Passing an object of a class type that has a nontrivial copy constructor, nontrivial move constructor, or nontrivial destructor as the second argument to + + va_start + + is conditionally supported with implementation-defined semantics ([expr.call] paragraph 7). +
    • +
    • + You may pass a parameter declared with the + + register + + keyword ([dcl.stc] paragraph 3) or a parameter with a function type. +
    -

    Passing an object of array type still produces undefined behavior in C++ because an array type as a function parameter requires the use of a reference, which is prohibited. Additionally, passing an object of a type that undergoes default argument promotions still produces undefined behavior in C++.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the object passed to va_start() will undergo a default argument promotion, which results in undefined behavior.

    - #include <cstdarg> +

    + Passing an object of array type still produces + + undefined behavior + + in C++ because an array type as a function parameter requires theย use of a reference, which is prohibited. Additionally, passing an object of a type that undergoes default argument promotions still produces undefined behavior in C++. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the object passed to + + va_start() + + will undergo a default argument promotion, which results in undefined behavior. +

    + + #include <cstdarg> extern "C" void f(float a, ...) { va_list list; va_start(list, a); // ... va_end(list); -} +} +
    -

    In this compliant solution, f() accepts a double instead of a float.

    - #include <cstdarg> +

    + In this compliant solution, + + f() + + accepts a + + double + + instead of a + + float. + +

    + + #include <cstdarg> extern "C" void f(double a, ...) { va_list list; @@ -37,11 +153,17 @@ extern "C" void f(double a, ...) { // ... va_end(list); } - +
    -

    In this noncompliant code example, a reference type is passed as the second argument to va_start().

    - #include <cstdarg> +

    + In this noncompliant code example, a reference type is passed as the second argument to + + va_start(). + +

    + + #include <cstdarg> #include <iostream> extern "C" void f(int &a, ...) { @@ -52,11 +174,19 @@ extern "C" void f(int &a, ...) { a = 100; // Assign something to a for the caller } va_end(list); -} +} +
    -

    Instead of passing a reference type to f(), this compliant solution passes a pointer type.

    - #include <cstdarg> +

    + Instead of passing a reference type to + + f() + + , this compliant solution passes a pointer type. +

    + + #include <cstdarg> #include <iostream> extern "C" void f(int *a, ...) { @@ -68,11 +198,26 @@ extern "C" void f(int *a, ...) { } va_end(list); } - +
    -

    In this noncompliant code example, a class with a nontrivial copy constructor (std::string) is passed as the second argument to va_start(), which is conditionally supported depending on the implementation.

    - #include <cstdarg> +

    + In this noncompliant code example, a class with a nontrivial copy constructor ( + + std::string + + )ย is passed as the second argument to + + va_start() + + , which is conditionally supported depending on the + + implementation + + . +

    + + #include <cstdarg> #include <iostream> #include <string> @@ -81,11 +226,23 @@ extern "C" void f(std::string s, ...) { va_start(list, s); std::cout << s << ", " << va_arg(list, int); va_end(list); -} +} +
    -

    This compliant solution passes a const char * instead of a std::string, which has well-defined behavior on all implementations.

    - #include <cstdarg> +

    + This compliant solution passes a + + const char * + + instead of a + + std::string + + , which has well-defined behavior on all implementations. +

    + + #include <cstdarg> #include <iostream> extern "C" void f(const char *s, ...) { @@ -93,10 +250,25 @@ extern "C" void f(const char *s, ...) { va_start(list, s); std::cout << (s ? s : "") << ", " << va_arg(list, int); va_end(list); -} +} +
    -

    Passing an object of an unsupported type as the second argument to va_start() can result in undefined behavior that might be exploited to cause data integrity violations.

    +

    + Passing an object of an unsupported type as the second argument to + + va_start() + + can result in + + undefined behavior + + that might be + + exploited + + to cause data integrity violations. +

    Subclause 7.16.1.4, "The - va_start + + va_start + Macro"
    @@ -133,10 +305,14 @@ extern "C" void f(const char *s, ...) { Medium @@ -169,7 +345,9 @@ extern "C" void f(const char *s, ...) { 3.9 @@ -204,7 +384,9 @@ extern "C" void f(const char *s, ...) { 2021.2
    - P4 + + P4 + - L3 + + L3 +
    - -Wvarargs + + -Wvarargs + Does not catch the violation in the third noncompliant code example (it is conditionally supported by @@ -189,7 +367,9 @@ extern "C" void f(const char *s, ...) { 2021.2 - C++3852, C++3853 + + C++3852, C++3853 + - CERT_CPP-EXP58-a + + CERT_CPP-EXP58-a + Use macros for variable arguments correctly @@ -232,7 +414,17 @@ extern "C" void f(const char *s, ...) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -265,7 +457,9 @@ extern "C" void f(const char *s, ...) { diff --git a/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember-standard.qhelp b/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember-standard.qhelp index b343ea0fd9..ef6f2c5a40 100644 --- a/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember-standard.qhelp +++ b/cpp/cert/src/rules/EXP59-CPP/OffsetUsedOnInvalidTypeOrMember-standard.qhelp @@ -1,35 +1,193 @@
    -

    The offsetof() macro is defined by the C Standard as a portable way to determine the offset, expressed in bytes, from the start of the object to a given member of that object. The C Standard, subclause 7.17, paragraph 3 [ISO/IEC 9899:1999], in part, specifies the following:

    +

    + The + + offsetof() + + macro is defined by the C Standard as a portable way to determine the offset, expressed in bytes, from the start of the object to a given member of that object. The C Standard, subclause 7.17, paragraph 3 [ + + ISO/IEC 9899:1999 + + ],ย in part, specifies the following: +

    -

    offsetof(type, member-designator) which expands to an integer constant expression that has type size_t, the value of which is the offset in bytes, to the structure member (designated by member-designator), from the beginning of its structure (designated by type). The type and member designator shall be such that given static type t; then the expression &(t.member-designator) evaluates to an address constant. (If the specified member is a bit-field, the behavior is undefined.)

    +

    + + offsetof(type, member-designator) + + which expands to an integer constant expression that has type + + size_t + + , the value of which is the offset in bytes, to the structure member (designated by + + member-designator + + ), from the beginning of its structure (designated by + + type + + ). The type and member designator shall be such that given + + static type t; + + then the expression + + &(t.member-designator) + + evaluates to an address constant. (If the specified member is a bit-field, the behavior is undefined.) +

    -

    The C++ Standard, [support.types], paragraph 4 [ISO/IEC 14882-2014], places additional restrictions beyond those set by the C Standard:

    +

    + The C++ Standard,ย [support.types], paragraph 4ย [ + + ISO/IEC 14882-2014 + + ],ย places additional restrictions beyond those set by the C Standard: +

    -

    The macro offsetof(type, member-designator) accepts a restricted set of type arguments in this International Standard. If type is not a standard-layout class, the results are undefined. The expression offsetof(type, member-designator) is never type-dependent and it is value-dependent if and only if type is dependent. The result of applying the offsetof macro to a field that is a static data member or a function member is undefined. No operation invoked by the offsetof macro shall throw an exception and noexcept(offsetof(type, member-designator)) shall be true.

    +

    + The macro + + offsetof(type, member-designator) + + accepts a restricted set of + + type + + arguments in this Internationalย Standard. If + + type + + is not a + + standard-layout class + + , the results are undefined. The expression + + offsetof(type, member-designator) + + is never type-dependent and it is value-dependent if and only if + + type + + is dependent. The result of applying the + + offsetof + + macro to a field that is a static dataย member or a function member is undefined. No operation invoked by the + + offsetof + + macro shall throw anย exception and + + noexcept(offsetof(type, member-designator)) + + shall be true. +

    -

    When specifying the type argument for the offsetof() macro, pass only a standard-layout class. The full description of a standard-layout class can be found in paragraph 7 of the [class] clause of the C++ Standard, or the type can be checked with the std::is_standard_layout<> type trait. When specifying the member designator argument for the offsetof() macro, do not pass a bit-field, static data member, or function member. Passing an invalid type or member to the offsetof() macro is undefined behavior.

    +

    + When specifying the type argument for the + + offsetof() + + macro, pass onlyย a standard-layout class. The full description of a standard-layout class can be found in paragraph 7 of theย [class] clauseย of the C++ Standard, or the type can be checked with the + + std::is_standard_layout<> + + type trait. When specifying the member designator argument for the + + offsetof() + + macro, do not pass a bit-field, static data member, or function member. Passing an invalid type or member to the + + offsetof() + + macro is + + undefined behavior + + . +

    -

    In this noncompliant code example, a type that is not a standard-layout class is passed to the offsetof() macro, resulting in undefined behavior.

    - #include <cstddef> - +

    + In this noncompliant code example, a type that is not a standard-layout class is passed to the + + offsetof() + + macro, resulting in + + undefined behavior + + . +

    + + #include <cstddef> +ย  struct D { virtual void f() {} int i; }; - +ย  void f() { size_t off = offsetof(D, i); // ... -} -

    Implementation Details

    -

    The noncompliant code example does not emit a diagnostic when compiled with the /Wall switch in Microsoft Visual Studio 2015 on x86, resulting in off being 4, due to the presence of a vtable for type D.

    +} +
    +

    + + Implementation Details + +

    +

    + The noncompliant code example does not emit a diagnostic when compiled with the + + /Wall + + switch in + + Microsoft Visual Studio + + 2015 on x86, resulting in + + off + + being + + 4 + + , due to the presence of a vtable for type + + D + + . +

    -

    It is not possible to determine the offset to i within D because D is not a standard-layout class. However, it is possible to make a standard-layout class within D if this functionality is critical to the application, as demonstrated by this compliant solution.

    - #include <cstddef> +

    + It is not possible to determine the offset to + + i + + within + + D + + because + + D + + is not a standard-layout class. However, it is possible to make a standard-layout class within + + D + + if this functionality is critical to the application, as demonstrated by this compliant solution. +

    + + #include <cstddef> struct D { virtual void f() {} @@ -41,31 +199,85 @@ struct D { void f() { size_t off = offsetof(D::InnerStandardLayout, i); // ... -} +} +
    -

    In this noncompliant code example, the offset to i is calculated so that a value can be stored at that offset within buffer. However, because i is a static data member of the class, this example results in undefined behavior. According to the C++ Standard, [class.static.data], paragraph 1 [ISO/IEC 14882-2014], static data members are not part of the subobjects of a class.

    - #include <cstddef> - +

    + In this noncompliant code example, the offset to + + i + + is calculated so that a value can be stored at that offset within + + buffer + + . However, because + + i + + is a static data member of the class, this example results in + + undefined behavior + + . According to the C++ Standard, [class.static.data], paragraph 1ย [ + + ISO/IEC 14882-2014 + + ], static data members are not part of the subobjects of a class. +

    + + #include <cstddef> +ย  struct S { static int i; // ... }; int S::i = 0; - +ย  extern void store_in_some_buffer(void *buffer, size_t offset, int val); extern void *buffer; - +ย  void f() { size_t off = offsetof(S, i); store_in_some_buffer(buffer, off, 42); -} -

    Implementation Details

    -

    The noncompliant code example does not emit a diagnostic when compiled with the /Wall switch in Microsoft Visual Studio 2015 on x86, resulting in off being a large value representing the offset between the null pointer address 0 and the address of the static variable S::i.

    +} +
    +

    + + Implementation Details + +

    +

    + The noncompliant code example does not emit a diagnostic when compiled with the + + /Wall + + switch in Microsoft Visual Studio 2015 on x86, resulting in + + off + + being a large value representing the offset between the null pointer address + + 0 + + and the address of the static variable + + S::i + + . +

    -

    Because static data members are not a part of the class layout, but are instead an entity of their own, this compliant solution passes the address of the static member variable as the buffer to store the data in and passes 0 as the offset.

    - #include <cstddef> +

    + Because static data members are not a part of the class layout, but are instead an entity of their own, this compliant solution passes the address of the static member variable as the buffer to store the data in and passes + + 0 + + as the offset. +

    + + #include <cstddef> struct S { static int i; @@ -77,10 +289,25 @@ extern void store_in_some_buffer(void *buffer, size_t offset, int val); void f() { store_in_some_buffer(&S::i, 0, 42); -} +} +
    -

    Passing an invalid type or member to offsetof() can result in undefined behavior that might be exploited to cause data integrity violations or result in incorrect values from the macro expansion.

    +

    + Passing an invalid type or member to + + offsetof() + + can result in + + undefined behavior + + that might be + + exploited + + to cause data integrity violations orย result in incorrect values from the macro expansion. +

    Subclause 7.16.1.4, "The - va_start + + va_start + Macro"
    @@ -117,15 +344,20 @@ void f() { Medium
    - P4 + + P4 + - L3 + + L3 +
    -

    Automated Detection

    +
    +
    @@ -152,7 +384,9 @@ void f() { 7.2.0 @@ -167,7 +401,9 @@ void f() { 3.9 @@ -213,7 +453,9 @@ void f() { 2021.2
    - CertC++-EXP59 + + CertC++-EXP59 + - -Winvalid-offsetof + + -Winvalid-offsetof + Emits an error diagnostic on invalid member designators, and emits a warning diagnostic on invalid types. @@ -182,7 +418,9 @@ void f() { - -Winvalid-offsetof + + -Winvalid-offsetof + Emits an error diagnostic on invalid member designators, and emits a warning diagnostic on invalid types. @@ -198,7 +436,9 @@ void f() { 2021.2 - C++3915, C++3916 + + C++3915, C++3916 + - CERT_CPP-EXP59-a + + CERT_CPP-EXP59-a + Use offsetof() on valid types and members @@ -241,7 +483,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -256,7 +508,9 @@ void f() { diff --git a/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries-standard.qhelp b/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries-standard.qhelp index 75d55c85f8..fcadfc2de6 100644 --- a/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries-standard.qhelp +++ b/cpp/cert/src/rules/EXP60-CPP/DoNotPassANonstandardObjectAcrossBoundaries-standard.qhelp @@ -1,40 +1,125 @@
    -

    Standard-layout types can be used to communicate with code written in other programming languages, as the layout of the type is strictly specified. The C++ Standard, [class], paragraph 7 [ISO/IEC 14882-2014], defines a standard-layout class as a class that

    +

    + Standard-layout types can be used to communicate with code written in other programming languages, as the layout of the type is strictly specified.ย The C++ Standard, [class], paragraph 7 [ + + ISO/IEC 14882-2014 + + ], defines a standard-layout class as a class that +

      -
    • does not have virtual functions,
    • -
    • has the same access control for all nonstatic data members,
    • -
    • has no base classes of the same type as the first nonstatic data member,
    • -
    • has nonstatic data members declared in only one class within the class hierarchy, and
    • -
    • recursively, does not have nonstatic data members of nonstandard-layout type.
    • +
    • + does not have virtual functions, +
    • +
    • + has the same access control for all nonstatic data members, +
    • +
    • + has no base classes of the same type as the first nonstatic data member, +
    • +
    • + has nonstatic data members declared in only one class within the class hierarchy, and +
    • +
    • + recursively, does not have nonstatic data members of nonstandard-layout type. +
    -

    An execution boundary is the delimitation between code compiled by differing compilers, including different versions of a compiler produced by the same vendor. For instance, a function may be declared in a header file but defined in a library that is loaded at runtime. The execution boundary exists between the call site in the executable and the function implementation in the library. Such boundaries are also called ABI (application binary interface) boundaries because they relate to the interoperability of application binaries.

    -

    Do not make any assumptions about the specific layout of objects with nonstandard-layout types. For objects compiled by one compiler that are referenced by code compiled by a different compiler, such assumptions cause correctness and portability concerns. The layout of the object generated by the first compiler is not guaranteed to be identical to the layout generated by the second compiler, even if both compilers are conforming C++ implementations. However, some implementations may document binary compatibility guarantees that can be relied on for passing nonstandard-layout objects between execution boundaries.

    -

    A special instance of this guidance involves non-C++ code compiled by a different compiler, such as C standard library implementations that are exposed via the C++ standard library. C standard library functions are exposed with C++ signatures, and the type system frequently assists in ensuring that types match appropriately. This process disallows passing a pointer to a C++ object to a function expecting a char * without additional work to suppress the type mismatch. However, some C standard library functions accept a void * for which any C++ pointer type will suffice. Passing a pointer to a nonstandard-layout type in this situation results in indeterminate behavior because it depends on the behavior of the other language as well as on the layout of the given object. For more information, see rule EXP56-CPP. Do not call a function with a mismatched language linkage.

    -

    Pass a nonstandard-layout type object across execution boundaries only when both sides of the execution boundary adhere to the same ABI. This is permissible if the same version of a compiler is used to compile both sides of the execution boundary, if the compiler used to compile both sides of the execution boundary is ABI-compatible across multiple versions, or if the differing compilers document that they adhere to the same ABI.

    +

    + An + + execution boundary + + is the delimitation between code compiled by differing compilers, including different versions of a compiler produced by the same vendor. For instance, a function may be declared in a header file but defined in a library that is loaded at runtime. The execution boundary exists between the call site in the executable and the function implementation in the library. Such boundaries are also called + + ABI + + (application binary interface) boundaries because they relate to the interoperability of application binaries. +

    +

    + Do not make any assumptions about the specific layout of objects with nonstandard-layout types. For objects compiled by one compiler that are referenced by code compiled by a different compiler, such assumptions cause correctness and portability concerns. The layout of the object generated by the first compiler is not guaranteed to be identical to the layout generated by the second compiler, even if both compilers are + + conforming + + C++ + + implementations + + . However, some implementations may document binary compatibility guarantees that can be relied on for passing nonstandard-layout objects between execution boundaries. +

    +

    + A special instance of this guidance involves non-C++ code compiled by a different compiler, such as C standard library implementations that are exposed via the C++ standard library. C standard library functions are exposed with C++ signatures, and the type system frequently assists in ensuring that types match appropriately. This process disallows passing a pointer to a C++ object to a function expecting a + + char * + + without additional work to suppress the type mismatch. However, some C standard library functions accept a + + void * + + for which any C++ pointer type will suffice. Passing a pointer to a nonstandard-layout type in this situation results in indeterminate behavior because it depends on the behavior of the other language as well as on the layout of the given object. For more information, see rule + + EXP56-CPP. Do not call a function with a mismatched language linkage + + . +

    +

    + Pass a nonstandard-layout type object across execution boundaries onlyย when both sides of the execution boundary adhere to the same ABI. This is permissible if the same version of a compiler is used to compile both sides of the execution boundary, if the compiler used to compile both sides of the execution boundary is ABI-compatible across multiple versions, or if the differing compilers document that they adhere to the same ABI. +

    -

    This noncompliant code example assumes that there is a library whose header is library.h, an application (represented by application.cpp), and that the library and application are not ABI-compatible. Therefore, the contents of library.h constitute an execution boundary. A nonstandard-layout type object S is passed across this execution boundary. The application creates an instance of an object of this type, then passes a reference to the object to a function defined by the library, crossing the execution boundary. Because the layout is not guaranteed to be compatible across the boundary, this results in unexpected behavior.

    - // library.h +

    + This noncompliant code example assumes that there is a library whose header is + + library.h + + , an application (represented by + + application.cpp + + ), and that the library and application are not ABI-compatible. Therefore, the contents of + + library.h + + constitute an execution boundary.ย Aย nonstandard-layout type object + + S + + is passed across this execution boundary. The application creates an instance of an object of this type, then passes a reference to the object to a function defined by the library, crossing the execution boundary. Because the layout is not guaranteed to be compatible across the boundary, this results in unexpected behavior. +

    + + // library.h struct S { virtual void f() { /* ... */ } }; - +ย  void func(S &s); // Implemented by the library, calls S::f() - +ย  // application.cpp #include "library.h" - +ย  void g() { S s; func(s); -} -

    This example would be compliant if the library and the application conformed to the same ABI, either explicitly through vendor documentation or implicitly by virtue of using the same compiler version to compile both.

    +} +
    +

    + This example would be compliant if the library and the application conformed to the same ABI, either explicitly through vendor documentation or implicitly by virtue of using the same compiler version to compile both. +

    -
    -

    Because the library and application do not conform to the same ABI, this compliant solution modifies the library and application to work with a standard-layout type. Furthermore, it also adds a static_assert() to help guard against future code changes that accidentally modify S to no longer be a standard-layout type.

    - // library.h +
    +

    + Because the library and application do not conform to the same ABI, this compliant solution modifies the library and application to work with a standard-layout type. Furthermore, it also adds a + + static_assert() + + to help guard against future code changes that accidentally modify + + S + + to no longer be a standard-layout type. +

    + + // library.h #include <type_traits> struct S { @@ -50,27 +135,63 @@ void func(S &s); // Implemented by the library, calls S::f() void g() { S s; func(s); -} +} +
    -

    In this noncompliant code example, a pointer to an object of nonstandard-layout type is passed to a function that has a "Fortran" language linkage. Language linkages other than "C" and "C++" are conditionally supported with implementation-defined semantics [ISO/IEC 14882-2014]. If the implementation does not support this language linkage, the code is ill-formed. Assuming that the language linkage is supported, any operations performed on the object passed may result in indeterminate behavior, which could have security implications.

    - struct B { +

    + In this noncompliant code example, a pointer to an object of nonstandard-layout type is passed to a function that has a + + "Fortran" + + language linkage. Language linkages other than + + "C" + + and + + "C++" + + are conditionally supported with implementation-defined semanticsย [ + + ISO/IEC 14882-2014 + + ]. If the + + implementation + + does not support this language linkage, the code is + + ill-formed + + . Assuming that the language linkage is supported, any operations performed on the object passed may result in indeterminate behavior, which could have security implications. +

    + + struct B { int i, j; }; - +ย  struct D : B { float f; }; - +ย  extern "Fortran" void func(void *); - +ย  void foo(D *d) { func(d); -} +} +
    -

    In this compliant solution, the nonstandard-layout type object is serialized into a local standard-layout type object, which is then passed to the Fortran function.

    - struct B { +

    + In this compliant solution, the nonstandard-layout type object is serialized into a local standard-layout type object, which is then passed to the + + Fortran + + function. +

    + + struct B { int i, j; }; @@ -85,16 +206,23 @@ void foo(D *d) { int i, j; float f; } temp; - +ย  temp.i = d->i; temp.j = d->j; temp.f = d->f; func(&temp); -} +} +
    -

    The effects of passing objects of nonstandard-layout type across execution boundaries depends on what operations are performed on the object within the callee as well as what subsequent operations are performed on the object from the caller. The effects can range from correct or benign behavior to undefined behavior.

    +

    + The effects of passing objects of nonstandard-layout type across execution boundaries depends on what operations are performed on the object within the callee as well as what subsequent operations are performed on the object from the caller. The effects can range from correct or benign behavior to + + undefined behavior + + . +

    Subclause 7.17, "Common Definitions - <stddef.h> + + <stddef.h> + "
    @@ -131,10 +259,14 @@ void foo(D *d) { Medium @@ -167,7 +299,9 @@ void foo(D *d) { 3.9 @@ -198,7 +334,9 @@ void foo(D *d) { 2021.2
    - P12 + + P12 + - L1 + + L1 +
    - -Wdynamic-class-memaccess + + -Wdynamic-class-memaccess + Catches instances where the vtable pointer will be overwritten @@ -183,7 +317,9 @@ void foo(D *d) { 2021.2 - C++4741, C++4742, C++4743 + + C++4741, C++4742, C++4743 + - CERT_CPP-EXP60-a + + CERT_CPP-EXP60-a + Do not pass a nonstandard-layout type object across execution boundaries @@ -208,7 +346,17 @@ void foo(D *d) {
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference-standard.qhelp b/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference-standard.qhelp index 7bd69d24d9..1e7399289c 100644 --- a/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference-standard.qhelp +++ b/cpp/cert/src/rules/EXP61-CPP/EscapingLambdaObjectWithCaptureByReference-standard.qhelp @@ -1,12 +1,67 @@
    -

    Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the reaching scope) for use in the lambda's function body. These captures may be either explicit, by specifying the object to capture in the lambda's capture-list, or implicit, by using a capture-default and referring to the object within the lambda's function body. When capturing an object explicitly or implicitly, the capture-default indicates that the object is either captured by copy (using =) or captured by reference (using &). When an object is captured by copy, the lambda object will contain an unnamed nonstatic data member that is initialized to the value of the object being captured. This nonstatic data member's lifetime is that of the lambda object's lifetime. However, when an object is captured by reference, the lifetime of the referent is not tied to the lifetime of the lambda object.

    -

    Because entities captured are objects with automatic storage duration (or this), a general guideline is that functions returning a lambda object (including returning via a reference parameter), or storing a lambda object in a member variable or global, should not capture an entity by reference because the lambda object often outlives the captured reference object.

    -

    When a lambda object outlives one of its reference-captured objects, execution of the lambda object's function call operator results in undefined behavior once that reference-captured object is accessed. Therefore, a lambda object must not outlive any of its reference-captured objects. This is a specific instance of EXP54-CPP. Do not access an object outside of its lifetime.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the function g() returns a lambda, which implicitly captures the automatic local variable i by reference. When that lambda is returned from the call, the reference it captured will refer to a variable whose lifetime has ended. As a result, when the lambda is executed in f(), the use of the dangling reference in the lambda results in undefined behavior.

    - auto g() { +

    + Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the + + reaching scope + + ) for use in the lambda's function body. These captures may be either explicit, by specifying the object to capture in the lambda's + + capture-list + + , or implicit, by using a + + capture-default + + and referring to the object within the lambda's function body. When capturing an object explicitly or implicitly, the capture-default indicates that the object is either captured by copy (using + + =) + + or captured by reference (using + + & + + ). When an object is captured by copy, the lambda object will contain an unnamed nonstatic data member that is initialized to the value of the object being captured. This nonstatic data member's lifetime is that of the lambda object's lifetime. However, when an object is captured by reference, the lifetime of the referent is not tied to the lifetime of the lambda object. +

    +

    + Because entities captured are objects with automatic storage duration (or + + this + + ),ย a general guideline is that functions returning a lambda object (including returning via a reference parameter), or storing a lambda object in a member variable or global, should not capture an entity by reference because the lambda object often outlives the captured reference object. +

    +

    + When a lambda object outlives one of its reference-captured objects, execution of the lambda object's function call operator results in + + undefined behavior + + once that reference-captured object is accessed. Therefore, a lambda object must not outlive any of its reference-captured objects. This is a specific instance of + + EXP54-CPP. Do not access an object outside of its lifetime + + . +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the function + + g() + + returns a lambda, which implicitly capturesย the automatic local variable + + i + + by reference. When that lambda is returned from the call, the reference it captured will refer to a variable whose lifetime has ended. As a result, when the lambda is executed in + + f() + + , the use of the dangling reference in the lambda results inย undefined behavior. +

    + + auto g() { int i = 12; return [&] { i = 100; @@ -16,11 +71,19 @@ void f() { int j = g()(); -} +} +
    -

    In this compliant solution, the lambda does not capture i by reference but instead captures it by copy. Consequently, the lambda contains an implicit nonstatic data member whose lifetime is that of the lambda.

    - auto g() { +

    + In this compliant solution, the lambda does not capture + + i + + by reference but instead captures it by copy. Consequently, the lambda contains an implicit nonstatic data member whose lifetime is that of the lambda. +

    + + auto g() { int i = 12; return [=] () mutable { i = 100; @@ -30,11 +93,19 @@ void f() { void f() { int j = g()(); -} +} +
    -

    In this noncompliant code example, a lambda reference captures a local variable from an outer lambda. However, this inner lambda outlives the lifetime of the outer lambda and any automatic local variables it defines, resulting in undefined behavior when an inner lambda object is executed within f().

    - auto g(int val) { +

    + In this noncompliant code example, a lambda reference captures a local variable from an outer lambda. However, this inner lambda outlives the lifetime of the outer lambda and any automatic local variables it defines, resulting in undefined behavior when an inner lambda object is executed within + + f() + + . +

    + + auto g(int val) { auto outer = [val] { int i = val; auto inner = [&] { @@ -49,11 +120,19 @@ void f() { void f() { auto fn = g(12); int j = fn(); -} +} +
    -

    In this compliant solution, the inner lambda captures i by copy instead of by reference.

    - auto g(int val) { +

    + In this compliant solution, the inner lambda captures + + i + + by copy instead of by reference. +

    + + auto g(int val) { auto outer = [val] { int i = val; auto inner = [i] { @@ -67,10 +146,13 @@ void f() { void f() { auto fn = g(12); int j = fn(); -} +} +
    -

    Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code.

    +

    + Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code. +

    @@ -107,10 +189,14 @@ void f() { High @@ -143,7 +229,9 @@ void f() { 20.10 @@ -158,7 +246,9 @@ void f() { 2021.2 @@ -173,9 +263,15 @@ void f() { 2021.2 @@ -220,7 +320,17 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - invalid_pointer_dereference + + invalid_pointer_dereference + - C++4706, C++4707, C++4708 + + C++4706, C++4707, C++4708 + - CERT_CPP-EXP61-a - CERT_CPP-EXP61-b - CERT_CPP-EXP61-c + + CERT_CPP-EXP61-a + + + CERT_CPP-EXP61-b + + + CERT_CPP-EXP61-c + Never return lambdas that capture local objects by reference @@ -208,10 +304,14 @@ void f() { - 7.17 + 7.16 - V1047 + + + V1047 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference-standard.qhelp b/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference-standard.qhelp index 7bd69d24d9..1e7399289c 100644 --- a/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference-standard.qhelp +++ b/cpp/cert/src/rules/EXP61-CPP/ReturningLambdaObjectWithCaptureByReference-standard.qhelp @@ -1,12 +1,67 @@
    -

    Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the reaching scope) for use in the lambda's function body. These captures may be either explicit, by specifying the object to capture in the lambda's capture-list, or implicit, by using a capture-default and referring to the object within the lambda's function body. When capturing an object explicitly or implicitly, the capture-default indicates that the object is either captured by copy (using =) or captured by reference (using &). When an object is captured by copy, the lambda object will contain an unnamed nonstatic data member that is initialized to the value of the object being captured. This nonstatic data member's lifetime is that of the lambda object's lifetime. However, when an object is captured by reference, the lifetime of the referent is not tied to the lifetime of the lambda object.

    -

    Because entities captured are objects with automatic storage duration (or this), a general guideline is that functions returning a lambda object (including returning via a reference parameter), or storing a lambda object in a member variable or global, should not capture an entity by reference because the lambda object often outlives the captured reference object.

    -

    When a lambda object outlives one of its reference-captured objects, execution of the lambda object's function call operator results in undefined behavior once that reference-captured object is accessed. Therefore, a lambda object must not outlive any of its reference-captured objects. This is a specific instance of EXP54-CPP. Do not access an object outside of its lifetime.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the function g() returns a lambda, which implicitly captures the automatic local variable i by reference. When that lambda is returned from the call, the reference it captured will refer to a variable whose lifetime has ended. As a result, when the lambda is executed in f(), the use of the dangling reference in the lambda results in undefined behavior.

    - auto g() { +

    + Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the + + reaching scope + + ) for use in the lambda's function body. These captures may be either explicit, by specifying the object to capture in the lambda's + + capture-list + + , or implicit, by using a + + capture-default + + and referring to the object within the lambda's function body. When capturing an object explicitly or implicitly, the capture-default indicates that the object is either captured by copy (using + + =) + + or captured by reference (using + + & + + ). When an object is captured by copy, the lambda object will contain an unnamed nonstatic data member that is initialized to the value of the object being captured. This nonstatic data member's lifetime is that of the lambda object's lifetime. However, when an object is captured by reference, the lifetime of the referent is not tied to the lifetime of the lambda object. +

    +

    + Because entities captured are objects with automatic storage duration (or + + this + + ),ย a general guideline is that functions returning a lambda object (including returning via a reference parameter), or storing a lambda object in a member variable or global, should not capture an entity by reference because the lambda object often outlives the captured reference object. +

    +

    + When a lambda object outlives one of its reference-captured objects, execution of the lambda object's function call operator results in + + undefined behavior + + once that reference-captured object is accessed. Therefore, a lambda object must not outlive any of its reference-captured objects. This is a specific instance of + + EXP54-CPP. Do not access an object outside of its lifetime + + . +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the function + + g() + + returns a lambda, which implicitly capturesย the automatic local variable + + i + + by reference. When that lambda is returned from the call, the reference it captured will refer to a variable whose lifetime has ended. As a result, when the lambda is executed in + + f() + + , the use of the dangling reference in the lambda results inย undefined behavior. +

    + + auto g() { int i = 12; return [&] { i = 100; @@ -16,11 +71,19 @@ void f() { int j = g()(); -} +} +
    -

    In this compliant solution, the lambda does not capture i by reference but instead captures it by copy. Consequently, the lambda contains an implicit nonstatic data member whose lifetime is that of the lambda.

    - auto g() { +

    + In this compliant solution, the lambda does not capture + + i + + by reference but instead captures it by copy. Consequently, the lambda contains an implicit nonstatic data member whose lifetime is that of the lambda. +

    + + auto g() { int i = 12; return [=] () mutable { i = 100; @@ -30,11 +93,19 @@ void f() { void f() { int j = g()(); -} +} +
    -

    In this noncompliant code example, a lambda reference captures a local variable from an outer lambda. However, this inner lambda outlives the lifetime of the outer lambda and any automatic local variables it defines, resulting in undefined behavior when an inner lambda object is executed within f().

    - auto g(int val) { +

    + In this noncompliant code example, a lambda reference captures a local variable from an outer lambda. However, this inner lambda outlives the lifetime of the outer lambda and any automatic local variables it defines, resulting in undefined behavior when an inner lambda object is executed within + + f() + + . +

    + + auto g(int val) { auto outer = [val] { int i = val; auto inner = [&] { @@ -49,11 +120,19 @@ void f() { void f() { auto fn = g(12); int j = fn(); -} +} +
    -

    In this compliant solution, the inner lambda captures i by copy instead of by reference.

    - auto g(int val) { +

    + In this compliant solution, the inner lambda captures + + i + + by copy instead of by reference. +

    + + auto g(int val) { auto outer = [val] { int i = val; auto inner = [i] { @@ -67,10 +146,13 @@ void f() { void f() { auto fn = g(12); int j = fn(); -} +} +
    -

    Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code.

    +

    + Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code. +

    @@ -107,10 +189,14 @@ void f() { High @@ -143,7 +229,9 @@ void f() { 20.10 @@ -158,7 +246,9 @@ void f() { 2021.2 @@ -173,9 +263,15 @@ void f() { 2021.2 @@ -220,7 +320,17 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - invalid_pointer_dereference + + invalid_pointer_dereference + - C++4706, C++4707, C++4708 + + C++4706, C++4707, C++4708 + - CERT_CPP-EXP61-a - CERT_CPP-EXP61-b - CERT_CPP-EXP61-c + + CERT_CPP-EXP61-a + + + CERT_CPP-EXP61-b + + + CERT_CPP-EXP61-c + Never return lambdas that capture local objects by reference @@ -208,10 +304,14 @@ void f() { - 7.17 + 7.16 - V1047 + + + V1047 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation-standard.qhelp b/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation-standard.qhelp index 5937232e00..aa5d3059c4 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation-standard.qhelp +++ b/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation-standard.qhelp @@ -1,18 +1,114 @@
    -

    The C++ Standard, [basic.types], paragraph 9 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [basic.types], paragraph 9ย [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T.

    +

    + The + + object representation + + of an object of type + + T + + is the sequence of + + N + + + unsigned char + + objects taken up byย the object of type + + T + + , where + + N + + equals + + sizeof(T) + + . The + + value representation + + of an object is the set of bits thatย hold the value of type + + T + + . +

    -

    The narrow character types (char, signed char, and unsigned char)โ€”as well as some other integral types on specific platformsโ€”have an object representation that consists solely of the bits from the object's value representation. For such types, accessing any of the bits of the value representation is well-defined behavior. This form of object representation allows a programmer to access and modify an object solely based on its bit representation, such as by calling std::memcmp() on its object representation.

    -

    Other types, such as classes, may not have an object representation composed solely of the bits from the object's value representation. For instance, classes may have bit-field data members, padding inserted between data members, a vtable to support virtual method dispatch, or data members declared with different access privileges. For such types, accessing bits of the object representation that are not part of the object's value representation may result in undefined behavior depending on how those bits are accessed.

    -

    Do not access the bits of an object representation that are not part of the object's value representation. Even if the bits are accessed in a well-defined manner, such as through an array of unsigned char objects, the values represented by those bits are unspecified or implementation-defined, and reliance on any particular value can lead to abnormal program execution.

    +

    + The narrow character types ( + + char + + , + + signed char + + , and + + unsigned char + + )โ€”as well as some other integral types on specific platformsโ€”have an object representation that consists solely of the bits from the object's value representation. For such types, accessing any of the bits of the value representation is well-defined behavior. This form of object representation allows a programmer to access and modify an object solely based on its bit representation, such as by calling + + std::memcmp() + + on its object representation. +

    +

    + Other types, such as classes, may not have an object representation composed solely of the bits from the object's value representation. For instance, classes may have bit-field data members, padding inserted between data members, a + + vtable + + to support virtual method dispatch, or data members declared with different access privileges. For such types, accessing bits of the object representation that are not part of the object's value representation may result in + + undefined behavior + + depending on how those bits are accessed. +

    +

    + Do not access the bits of an object representation that are not part of the object's value representation.ย Even if the bits are accessed in a well-defined manner, such as through an array of + + unsigned char + + objects, the values represented by those bits are unspecified or implementation-defined, and reliance on any particular value can lead to abnormal program execution. +

    -

    In this noncompliant code example, the complete object representation is accessed when comparing two objects of type S. Per the C++ Standard, [class], paragraph 13 [ISO/IEC 14882-2014], classes may be padded with data to ensure that they are properly aligned in memory. The contents of the padding and the amount of padding added is implementation-defined. This can lead to incorrect results when comparing the object representation of classes instead of the value representation, as the padding may assume different unspecified values for each object instance.

    - #include <cstring> - +

    + In this noncompliant code example, the complete object representation is accessed when comparing two objects of type + + S + + . Per the C++ Standard, [class], paragraph 13ย [ + + ISO/IEC 14882-2014 + + ], classes may be padded with data to ensure that they are properly aligned in memory. The contents of the padding and the amount of padding added is + + implementation-defined + + . This can lead to incorrect results when comparing the object representation of classes instead of the value representation, as the padding may assume different + + unspecified values + + for each object instance. +

    + + #include <cstring> +ย  struct S { unsigned char buffType; int size; @@ -22,33 +118,65 @@ void f(const S &s1, const S &s2) { if (!std::memcmp(&s1, &s2, sizeof(S))) { // ... } -} +} +
    -

    In this compliant solution, S overloads operator==() to perform a comparison of the value representation of the object.

    - struct S { +

    + In this compliant solution, + + S + + overloads + + operator==() + + to perform a comparison of the value representation of the object. +

    + + struct S { unsigned char buffType; int size; - +ย  friend bool operator==(const S &lhs, const S &rhs) { return lhs.buffType == rhs.buffType && lhs.size == rhs.size; } }; - +ย  void f(const S &s1, const S &s2) { if (s1 == s2) { // ... } -} +} +
    -

    In this noncompliant code example, std::memset() is used to clear the internal state of an object. An implementation may store a vtable within the object instance due to the presence of a virtual function, and that vtable is subsequently overwritten by the call to std::memset(), leading to undefined behavior when virtual method dispatch is required.

    - #include <cstring> +

    + In this noncompliant code example, + + std::memset() + + is used to clear the internal state of an object. An + + implementation + + may store aย vtableย within the object instance due to the presence of a virtual function, and that vtable is subsequently overwritten by the call to + + std::memset() + + , leading to + + undefined behavior + + when virtual method dispatch is required. +

    + + #include <cstring> struct S { int i, j, k; - +ย  // ... virtual void f(); @@ -60,11 +188,22 @@ void f() { std::memset(s, 0, sizeof(S)); // ... s->f(); // undefined behavior -} +} +
    -

    In this compliant solution, the data members of S are cleared explicitly instead of calling std::memset().

    - struct S { +

    + In this compliant solution, the data members of + + S + + are cleared explicitly instead of calling + + std::memset(). + +

    + + struct S { int i, j, k; // ... @@ -79,26 +218,56 @@ void f() { s->clear(); // ... s->f(); // ok -} +} +
    -

    EXP62-CPP-EX1: It is permissible to access the bits of an object representation when that access is otherwise unobservable in well-defined code. Specifically, reading bits that are not part of the value representation is permissible when there is no reliance or assumptions placed on their values, and writing bits that are not part of the value representation is only permissible when those bits are padding bits. This exception does not permit writing to bits that are part of the object representation aside from padding bits, such as overwriting a vtable pointer.

    -

    For instance, it is acceptable to call std::memcpy() on an object containing a bit-field, as in the following example, because the read and write of the padding bits cannot be observed.

    - #include <cstring> - +

    + + EXP62-CPP-EX1: + + It is permissible to access the bits of an object representation when that access is otherwise unobservable in well-defined code. Specifically, reading bits that are not part of the value representation is permissible when there is no reliance or assumptions placed on their values, and writing bits that are not part of the value representation is only permissible when those bits are padding bits. This exception does not permit writing to bits that are part of the object representation aside from padding bits, such as overwriting a vtable pointer. +

    +

    + For instance, it is acceptable to call + + std::memcpy() + + on an object containing a bit-field, as in the following example, because the read and write of the padding bits cannot be observed. +

    + + #include <cstring> +ย  struct S { int i : 10; int j; }; - +ย  void f(const S &s1) { S s2; std::memcpy(&s2, &s1, sizeof(S)); -} -

    Code that complies with this exception must still comply with OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions.

    +} +
    +

    + Code that complies with this exception must still comply with + + OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions + + . +

    -
    -

    The effects of accessing bits of an object representation that are not part of the object's value representation can range from implementation-defined behavior (such as assuming the layout of fields with differing access controls) to code execution vulnerabilities (such as overwriting the vtable pointer).

    +
    +

    + The effects of accessing bits of an object representation that are not part of the object's value representation can range from + + implementation-defined behavior + + (such as assuming the layout of fields with differing access controls) to code execution + + vulnerabilities + + (such as overwriting the vtable pointer). +

    @@ -135,10 +304,14 @@ void f(const S &s1) { High @@ -171,27 +344,12 @@ void f(const S &s1) { 20.10 - - - - - - @@ -204,7 +362,9 @@ void f(const S &s1) { 2021.2 @@ -218,7 +378,9 @@ void f(const S &s1) { @@ -261,7 +433,17 @@ void f(const S &s1) {
    - P6 + + P6 + - L2 + + L2 +
    - invalid_pointer_dereferenceuninitialized_variable_use - -
    - - CodeSonar - - - 6.2p0 - - BADFUNC.MEMCMP - BADFUNC.MEMSET + + invalid_pointer_dereference + uninitialized_variable_use + - Use of memcmp - Use of memset
    - C++4726, C++4727, C++4728, C++4729, C++4731, C++4732, C++4733, C++4734 + + C++4726, C++4727, C++4728, C++4729, C++4731, C++4732, C++4733, C++4734 + - 618 S + + 618 S + Partially implemented @@ -234,7 +396,9 @@ void f(const S &s1) { 2021.2 - CERT_CPP-EXP62-a + + CERT_CPP-EXP62-a + Do not compare objects of a class that may contain padding bits with C standard library functions @@ -247,12 +411,20 @@ void f(const S &s1) { - 7.17 + 7.16 - V598 + + V598 + + + , - V780 + + + V780 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql b/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql index 81e82b68e1..c57a5f2f9b 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql +++ b/cpp/cert/src/rules/EXP62-CPP/MemcmpUsedToAccessObjectRepresentation.ql @@ -20,8 +20,7 @@ import VirtualTable from MemcmpBA cmp where not isExcluded(cmp, RepresentationPackage::memcmpUsedToAccessObjectRepresentationQuery()) and - cmp - .getBuffer(_, _) + cmp.getBuffer(_, _) .getUnconverted() .getUnspecifiedType() .(PointerType) diff --git a/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation-standard.qhelp b/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation-standard.qhelp index 5937232e00..aa5d3059c4 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation-standard.qhelp +++ b/cpp/cert/src/rules/EXP62-CPP/MemcpyUsedToAccessObjectRepresentation-standard.qhelp @@ -1,18 +1,114 @@
    -

    The C++ Standard, [basic.types], paragraph 9 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [basic.types], paragraph 9ย [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T.

    +

    + The + + object representation + + of an object of type + + T + + is the sequence of + + N + + + unsigned char + + objects taken up byย the object of type + + T + + , where + + N + + equals + + sizeof(T) + + . The + + value representation + + of an object is the set of bits thatย hold the value of type + + T + + . +

    -

    The narrow character types (char, signed char, and unsigned char)โ€”as well as some other integral types on specific platformsโ€”have an object representation that consists solely of the bits from the object's value representation. For such types, accessing any of the bits of the value representation is well-defined behavior. This form of object representation allows a programmer to access and modify an object solely based on its bit representation, such as by calling std::memcmp() on its object representation.

    -

    Other types, such as classes, may not have an object representation composed solely of the bits from the object's value representation. For instance, classes may have bit-field data members, padding inserted between data members, a vtable to support virtual method dispatch, or data members declared with different access privileges. For such types, accessing bits of the object representation that are not part of the object's value representation may result in undefined behavior depending on how those bits are accessed.

    -

    Do not access the bits of an object representation that are not part of the object's value representation. Even if the bits are accessed in a well-defined manner, such as through an array of unsigned char objects, the values represented by those bits are unspecified or implementation-defined, and reliance on any particular value can lead to abnormal program execution.

    +

    + The narrow character types ( + + char + + , + + signed char + + , and + + unsigned char + + )โ€”as well as some other integral types on specific platformsโ€”have an object representation that consists solely of the bits from the object's value representation. For such types, accessing any of the bits of the value representation is well-defined behavior. This form of object representation allows a programmer to access and modify an object solely based on its bit representation, such as by calling + + std::memcmp() + + on its object representation. +

    +

    + Other types, such as classes, may not have an object representation composed solely of the bits from the object's value representation. For instance, classes may have bit-field data members, padding inserted between data members, a + + vtable + + to support virtual method dispatch, or data members declared with different access privileges. For such types, accessing bits of the object representation that are not part of the object's value representation may result in + + undefined behavior + + depending on how those bits are accessed. +

    +

    + Do not access the bits of an object representation that are not part of the object's value representation.ย Even if the bits are accessed in a well-defined manner, such as through an array of + + unsigned char + + objects, the values represented by those bits are unspecified or implementation-defined, and reliance on any particular value can lead to abnormal program execution. +

    -

    In this noncompliant code example, the complete object representation is accessed when comparing two objects of type S. Per the C++ Standard, [class], paragraph 13 [ISO/IEC 14882-2014], classes may be padded with data to ensure that they are properly aligned in memory. The contents of the padding and the amount of padding added is implementation-defined. This can lead to incorrect results when comparing the object representation of classes instead of the value representation, as the padding may assume different unspecified values for each object instance.

    - #include <cstring> - +

    + In this noncompliant code example, the complete object representation is accessed when comparing two objects of type + + S + + . Per the C++ Standard, [class], paragraph 13ย [ + + ISO/IEC 14882-2014 + + ], classes may be padded with data to ensure that they are properly aligned in memory. The contents of the padding and the amount of padding added is + + implementation-defined + + . This can lead to incorrect results when comparing the object representation of classes instead of the value representation, as the padding may assume different + + unspecified values + + for each object instance. +

    + + #include <cstring> +ย  struct S { unsigned char buffType; int size; @@ -22,33 +118,65 @@ void f(const S &s1, const S &s2) { if (!std::memcmp(&s1, &s2, sizeof(S))) { // ... } -} +} +
    -

    In this compliant solution, S overloads operator==() to perform a comparison of the value representation of the object.

    - struct S { +

    + In this compliant solution, + + S + + overloads + + operator==() + + to perform a comparison of the value representation of the object. +

    + + struct S { unsigned char buffType; int size; - +ย  friend bool operator==(const S &lhs, const S &rhs) { return lhs.buffType == rhs.buffType && lhs.size == rhs.size; } }; - +ย  void f(const S &s1, const S &s2) { if (s1 == s2) { // ... } -} +} +
    -

    In this noncompliant code example, std::memset() is used to clear the internal state of an object. An implementation may store a vtable within the object instance due to the presence of a virtual function, and that vtable is subsequently overwritten by the call to std::memset(), leading to undefined behavior when virtual method dispatch is required.

    - #include <cstring> +

    + In this noncompliant code example, + + std::memset() + + is used to clear the internal state of an object. An + + implementation + + may store aย vtableย within the object instance due to the presence of a virtual function, and that vtable is subsequently overwritten by the call to + + std::memset() + + , leading to + + undefined behavior + + when virtual method dispatch is required. +

    + + #include <cstring> struct S { int i, j, k; - +ย  // ... virtual void f(); @@ -60,11 +188,22 @@ void f() { std::memset(s, 0, sizeof(S)); // ... s->f(); // undefined behavior -} +} +
    -

    In this compliant solution, the data members of S are cleared explicitly instead of calling std::memset().

    - struct S { +

    + In this compliant solution, the data members of + + S + + are cleared explicitly instead of calling + + std::memset(). + +

    + + struct S { int i, j, k; // ... @@ -79,26 +218,56 @@ void f() { s->clear(); // ... s->f(); // ok -} +} +
    -

    EXP62-CPP-EX1: It is permissible to access the bits of an object representation when that access is otherwise unobservable in well-defined code. Specifically, reading bits that are not part of the value representation is permissible when there is no reliance or assumptions placed on their values, and writing bits that are not part of the value representation is only permissible when those bits are padding bits. This exception does not permit writing to bits that are part of the object representation aside from padding bits, such as overwriting a vtable pointer.

    -

    For instance, it is acceptable to call std::memcpy() on an object containing a bit-field, as in the following example, because the read and write of the padding bits cannot be observed.

    - #include <cstring> - +

    + + EXP62-CPP-EX1: + + It is permissible to access the bits of an object representation when that access is otherwise unobservable in well-defined code. Specifically, reading bits that are not part of the value representation is permissible when there is no reliance or assumptions placed on their values, and writing bits that are not part of the value representation is only permissible when those bits are padding bits. This exception does not permit writing to bits that are part of the object representation aside from padding bits, such as overwriting a vtable pointer. +

    +

    + For instance, it is acceptable to call + + std::memcpy() + + on an object containing a bit-field, as in the following example, because the read and write of the padding bits cannot be observed. +

    + + #include <cstring> +ย  struct S { int i : 10; int j; }; - +ย  void f(const S &s1) { S s2; std::memcpy(&s2, &s1, sizeof(S)); -} -

    Code that complies with this exception must still comply with OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions.

    +} +
    +

    + Code that complies with this exception must still comply with + + OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions + + . +

    -
    -

    The effects of accessing bits of an object representation that are not part of the object's value representation can range from implementation-defined behavior (such as assuming the layout of fields with differing access controls) to code execution vulnerabilities (such as overwriting the vtable pointer).

    +
    +

    + The effects of accessing bits of an object representation that are not part of the object's value representation can range from + + implementation-defined behavior + + (such as assuming the layout of fields with differing access controls) to code execution + + vulnerabilities + + (such as overwriting the vtable pointer). +

    @@ -135,10 +304,14 @@ void f(const S &s1) { High @@ -171,27 +344,12 @@ void f(const S &s1) { 20.10 - - - - - - @@ -204,7 +362,9 @@ void f(const S &s1) { 2021.2 @@ -218,7 +378,9 @@ void f(const S &s1) { @@ -261,7 +433,17 @@ void f(const S &s1) {
    - P6 + + P6 + - L2 + + L2 +
    - invalid_pointer_dereferenceuninitialized_variable_use - -
    - - CodeSonar - - - 6.2p0 - - BADFUNC.MEMCMP - BADFUNC.MEMSET + + invalid_pointer_dereference + uninitialized_variable_use + - Use of memcmp - Use of memset
    - C++4726, C++4727, C++4728, C++4729, C++4731, C++4732, C++4733, C++4734 + + C++4726, C++4727, C++4728, C++4729, C++4731, C++4732, C++4733, C++4734 + - 618 S + + 618 S + Partially implemented @@ -234,7 +396,9 @@ void f(const S &s1) { 2021.2 - CERT_CPP-EXP62-a + + CERT_CPP-EXP62-a + Do not compare objects of a class that may contain padding bits with C standard library functions @@ -247,12 +411,20 @@ void f(const S &s1) { - 7.17 + 7.16 - V598 + + V598 + + + , - V780 + + + V780 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation-standard.qhelp b/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation-standard.qhelp index 5937232e00..aa5d3059c4 100644 --- a/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation-standard.qhelp +++ b/cpp/cert/src/rules/EXP62-CPP/MemsetUsedToAccessObjectRepresentation-standard.qhelp @@ -1,18 +1,114 @@
    -

    The C++ Standard, [basic.types], paragraph 9 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [basic.types], paragraph 9ย [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T.

    +

    + The + + object representation + + of an object of type + + T + + is the sequence of + + N + + + unsigned char + + objects taken up byย the object of type + + T + + , where + + N + + equals + + sizeof(T) + + . The + + value representation + + of an object is the set of bits thatย hold the value of type + + T + + . +

    -

    The narrow character types (char, signed char, and unsigned char)โ€”as well as some other integral types on specific platformsโ€”have an object representation that consists solely of the bits from the object's value representation. For such types, accessing any of the bits of the value representation is well-defined behavior. This form of object representation allows a programmer to access and modify an object solely based on its bit representation, such as by calling std::memcmp() on its object representation.

    -

    Other types, such as classes, may not have an object representation composed solely of the bits from the object's value representation. For instance, classes may have bit-field data members, padding inserted between data members, a vtable to support virtual method dispatch, or data members declared with different access privileges. For such types, accessing bits of the object representation that are not part of the object's value representation may result in undefined behavior depending on how those bits are accessed.

    -

    Do not access the bits of an object representation that are not part of the object's value representation. Even if the bits are accessed in a well-defined manner, such as through an array of unsigned char objects, the values represented by those bits are unspecified or implementation-defined, and reliance on any particular value can lead to abnormal program execution.

    +

    + The narrow character types ( + + char + + , + + signed char + + , and + + unsigned char + + )โ€”as well as some other integral types on specific platformsโ€”have an object representation that consists solely of the bits from the object's value representation. For such types, accessing any of the bits of the value representation is well-defined behavior. This form of object representation allows a programmer to access and modify an object solely based on its bit representation, such as by calling + + std::memcmp() + + on its object representation. +

    +

    + Other types, such as classes, may not have an object representation composed solely of the bits from the object's value representation. For instance, classes may have bit-field data members, padding inserted between data members, a + + vtable + + to support virtual method dispatch, or data members declared with different access privileges. For such types, accessing bits of the object representation that are not part of the object's value representation may result in + + undefined behavior + + depending on how those bits are accessed. +

    +

    + Do not access the bits of an object representation that are not part of the object's value representation.ย Even if the bits are accessed in a well-defined manner, such as through an array of + + unsigned char + + objects, the values represented by those bits are unspecified or implementation-defined, and reliance on any particular value can lead to abnormal program execution. +

    -

    In this noncompliant code example, the complete object representation is accessed when comparing two objects of type S. Per the C++ Standard, [class], paragraph 13 [ISO/IEC 14882-2014], classes may be padded with data to ensure that they are properly aligned in memory. The contents of the padding and the amount of padding added is implementation-defined. This can lead to incorrect results when comparing the object representation of classes instead of the value representation, as the padding may assume different unspecified values for each object instance.

    - #include <cstring> - +

    + In this noncompliant code example, the complete object representation is accessed when comparing two objects of type + + S + + . Per the C++ Standard, [class], paragraph 13ย [ + + ISO/IEC 14882-2014 + + ], classes may be padded with data to ensure that they are properly aligned in memory. The contents of the padding and the amount of padding added is + + implementation-defined + + . This can lead to incorrect results when comparing the object representation of classes instead of the value representation, as the padding may assume different + + unspecified values + + for each object instance. +

    + + #include <cstring> +ย  struct S { unsigned char buffType; int size; @@ -22,33 +118,65 @@ void f(const S &s1, const S &s2) { if (!std::memcmp(&s1, &s2, sizeof(S))) { // ... } -} +} +
    -

    In this compliant solution, S overloads operator==() to perform a comparison of the value representation of the object.

    - struct S { +

    + In this compliant solution, + + S + + overloads + + operator==() + + to perform a comparison of the value representation of the object. +

    + + struct S { unsigned char buffType; int size; - +ย  friend bool operator==(const S &lhs, const S &rhs) { return lhs.buffType == rhs.buffType && lhs.size == rhs.size; } }; - +ย  void f(const S &s1, const S &s2) { if (s1 == s2) { // ... } -} +} +
    -

    In this noncompliant code example, std::memset() is used to clear the internal state of an object. An implementation may store a vtable within the object instance due to the presence of a virtual function, and that vtable is subsequently overwritten by the call to std::memset(), leading to undefined behavior when virtual method dispatch is required.

    - #include <cstring> +

    + In this noncompliant code example, + + std::memset() + + is used to clear the internal state of an object. An + + implementation + + may store aย vtableย within the object instance due to the presence of a virtual function, and that vtable is subsequently overwritten by the call to + + std::memset() + + , leading to + + undefined behavior + + when virtual method dispatch is required. +

    + + #include <cstring> struct S { int i, j, k; - +ย  // ... virtual void f(); @@ -60,11 +188,22 @@ void f() { std::memset(s, 0, sizeof(S)); // ... s->f(); // undefined behavior -} +} +
    -

    In this compliant solution, the data members of S are cleared explicitly instead of calling std::memset().

    - struct S { +

    + In this compliant solution, the data members of + + S + + are cleared explicitly instead of calling + + std::memset(). + +

    + + struct S { int i, j, k; // ... @@ -79,26 +218,56 @@ void f() { s->clear(); // ... s->f(); // ok -} +} +
    -

    EXP62-CPP-EX1: It is permissible to access the bits of an object representation when that access is otherwise unobservable in well-defined code. Specifically, reading bits that are not part of the value representation is permissible when there is no reliance or assumptions placed on their values, and writing bits that are not part of the value representation is only permissible when those bits are padding bits. This exception does not permit writing to bits that are part of the object representation aside from padding bits, such as overwriting a vtable pointer.

    -

    For instance, it is acceptable to call std::memcpy() on an object containing a bit-field, as in the following example, because the read and write of the padding bits cannot be observed.

    - #include <cstring> - +

    + + EXP62-CPP-EX1: + + It is permissible to access the bits of an object representation when that access is otherwise unobservable in well-defined code. Specifically, reading bits that are not part of the value representation is permissible when there is no reliance or assumptions placed on their values, and writing bits that are not part of the value representation is only permissible when those bits are padding bits. This exception does not permit writing to bits that are part of the object representation aside from padding bits, such as overwriting a vtable pointer. +

    +

    + For instance, it is acceptable to call + + std::memcpy() + + on an object containing a bit-field, as in the following example, because the read and write of the padding bits cannot be observed. +

    + + #include <cstring> +ย  struct S { int i : 10; int j; }; - +ย  void f(const S &s1) { S s2; std::memcpy(&s2, &s1, sizeof(S)); -} -

    Code that complies with this exception must still comply with OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions.

    +} +
    +

    + Code that complies with this exception must still comply with + + OOP57-CPP. Prefer special member functions and overloaded operators to C Standard Library functions + + . +

    -
    -

    The effects of accessing bits of an object representation that are not part of the object's value representation can range from implementation-defined behavior (such as assuming the layout of fields with differing access controls) to code execution vulnerabilities (such as overwriting the vtable pointer).

    +
    +

    + The effects of accessing bits of an object representation that are not part of the object's value representation can range from + + implementation-defined behavior + + (such as assuming the layout of fields with differing access controls) to code execution + + vulnerabilities + + (such as overwriting the vtable pointer). +

    @@ -135,10 +304,14 @@ void f(const S &s1) { High @@ -171,27 +344,12 @@ void f(const S &s1) { 20.10 - - - - - - @@ -204,7 +362,9 @@ void f(const S &s1) { 2021.2 @@ -218,7 +378,9 @@ void f(const S &s1) { @@ -261,7 +433,17 @@ void f(const S &s1) {
    - P6 + + P6 + - L2 + + L2 +
    - invalid_pointer_dereferenceuninitialized_variable_use - -
    - - CodeSonar - - - 6.2p0 - - BADFUNC.MEMCMP - BADFUNC.MEMSET + + invalid_pointer_dereference + uninitialized_variable_use + - Use of memcmp - Use of memset
    - C++4726, C++4727, C++4728, C++4729, C++4731, C++4732, C++4733, C++4734 + + C++4726, C++4727, C++4728, C++4729, C++4731, C++4732, C++4733, C++4734 + - 618 S + + 618 S + Partially implemented @@ -234,7 +396,9 @@ void f(const S &s1) { 2021.2 - CERT_CPP-EXP62-a + + CERT_CPP-EXP62-a + Do not compare objects of a class that may contain padding bits with C standard library functions @@ -247,12 +411,20 @@ void f(const S &s1) { - 7.17 + 7.16 - V598 + + V598 + + + , - V780 + + + V780 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject-standard.qhelp b/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject-standard.qhelp index 9e98b68835..d88d79aa5f 100644 --- a/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject-standard.qhelp +++ b/cpp/cert/src/rules/EXP63-CPP/DoNotRelyOnTheValueOfAMovedFromObject-standard.qhelp @@ -1,10 +1,38 @@
    -

    Many types, including user-defined types and types provided by the Standard Template Library, support move semantics. Except in rare circumstances, an object of a type that supports move operations (move initialization or move assignment) will be left in a valid, but unspecified state after the object's value has been moved.

    -

    Passing an object as a function argument that binds to an rvalue reference parameter, including via implicit function call syntax such as move assignment or move construction, moves the object's state into another object. Upon return from such a function call, the object that was bound as an rvalue reference parameter is considered to be in the moved-from state. Once an object is in the moved-from state, the only operations that may be safely performed on that object instance are ones for which the operation has no preconditions, because it is unknown whether the unspecified state of the object will satisfy those preconditions. While some types have explicitly-defined preconditions, such as types defined by the Standard Template Library, it should be assumed that the only operations that may be safely performed on a moved-from object instance are reinitialization through assignment into the object or terminating the lifetime of the object by invoking its destructor.

    -

    Do not rely on the value of a moved-from object unless the type of the object is documented to be in a well-specified state. While the object is guaranteed to be in a valid state, relying on unspecified values leads to unspecified behavior. Since the behavior need not be documented, this can in turn result in abnormal program behavior and portability concerns.

    -

    The following Standard Template Library functions are guaranteed to leave the moved-from object in a well-specified state.

    +

    + Many types, including user-defined types and types provided by the Standard Template Library, support move semantics. Except in rare circumstances, an object of a type that supports move operations (move initialization or move assignment) will be left in a valid, but unspecified state after the object's value has been moved. +

    +

    + Passing an object as a function argument that binds to an + + rvalue + + reference parameter, including via implicit function call syntax such as move assignment or move construction, + + moves + + the object's state into another object.ย Upon return from such a function call, the object that was bound as an rvalue reference parameter is considered to be in the + + moved-from + + state. Once an object is in the moved-from state, the only operations that may be safely performed on that object instance are ones for which the operation has no preconditions, because it is unknown whether the unspecified state of the object will satisfy those preconditions. While some types have explicitly-defined preconditions, such as types defined by the Standard Template Library, it should be assumed thatย the only operations that may be safely performed on a moved-from object instance are reinitialization through assignment into the object or terminating the lifetime of the object by invoking its destructor. +

    +

    + Do not rely on the value of a moved-from object unless the type of the object is documented to be in a well-specified state. While the object is guaranteed to be in a valid state, relying on + + unspecified values + + leads to + + unspecified behavior + + . Since the behavior need not be documented, this can in turn result in abnormal program behavior and portability concerns. +

    +

    + The following Standard Template Library functions are guaranteed to leave the moved-from object in a well-specified state. +

    @@ -20,13 +48,17 @@
    - std::unique_ptr + + std::unique_ptr + Move construction, Move assignment, "Converting" move construction, "Converting" move assignment (likewise for - std::unique_ptr + + std::unique_ptr + for array objects with a runtime length) @@ -39,7 +71,9 @@
    - std::shared_ptr + + std::shared_ptr + Move construction, Move assignment, @@ -51,11 +85,15 @@
    - std::shared_ptr + + std::shared_ptr + Move construction, Move assignment from a - std::unique_ptr + + std::unique_ptr + The moved-from object is guaranteed to refer to a null pointer value, per [util.smartptr.shared.const], paragraph 29 and [util.smartptr.shared.assign], paragraph 6. @@ -63,7 +101,9 @@
    - std::weak_ptr + + std::weak_ptr + Move construction, Move assignment, @@ -75,24 +115,36 @@
    - std::basic_ios + + std::basic_ios + - move() + + move() + The moved-from object is still left in an unspecified state, except that - rdbuf() + + rdbuf() + shall return the same value as it returned before the move, and - tie() + + tie() + shall return - 0 + + 0 + , per [basic.ios.members], paragraph 20.
    - std::basic_filebuf + + std::basic_filebuf + Move constructor, Move assignment @@ -103,20 +155,26 @@
    - std::thread + + std::thread + Move constructor, Move assignment The result from calling - get_id() + + get_id() + on the moved-from object is guaranteed to remain unchanged; otherwise the object is in an unspecified state, per [thread.thread.constr], paragraph 11 and [thread.thread.assign], paragraph 2.
    - std::unique_lock + + std::unique_lock + Move constructor, Move assignment @@ -127,7 +185,9 @@
    - std::shared_lock + + std::shared_lock + Move constructor, Move assignment @@ -138,7 +198,9 @@
    - std::promise + + std::promise + Move constructor, Move assignment @@ -149,22 +211,30 @@
    - std::future + + std::future + Move constructor, Move assignment Calling - valid() + + valid() + on the moved-from object is guaranteed to return - false + + false + , per [futures.unique_future], paragraphs 8 and 11.
    - std::shared_future + + std::shared_future + Move constructor, Move assignment, @@ -172,15 +242,21 @@ Calling - valid() + + valid() + on the moved-from object is guaranteed to return - false + + false + , per [futures.shared_future], paragraphs 8 and 11.
    - std::packaged_task + + std::packaged_task + Move constructor, Move assignment @@ -191,11 +267,58 @@
    -

    Several generic standard template library (STL) algorithms, such as std::remove() and std::unique(), remove instances of elements from a container without shrinking the size of the container. Instead, these algorithms return a ForwardIterator to indicate the partition within the container after which elements are no longer valid. The elements in the container that precede the returned iterator are valid elements with specified values; whereas the elements that succeed the returned iterator are valid but have unspecified values. Accessing unspecified values of elements iterated over results in unspecified behavior. Frequently, the erase-remove idiom is used to shrink the size of the container when using these algorithms.

    +

    + Several generic standard template library (STL) algorithms, such as + + std::remove() + + and + + std::unique() + + , remove instances of elements from a container without shrinking the size of the container. Instead, these algorithms return a + + ForwardIterator + + to indicate the partition within the container after which elements are no longer valid. The elements in the container that precede the returned iterator are valid elements with specified values; whereas the elements that + succeed + the returned iterator are valid but have unspecified values.ย Accessing + + unspecified values + + of elements iterated over results in + + unspecified behavior + + . Frequently, the + + erase-remove idiom + + is used to shrink the size of the container when using these algorithms. +

    -
    -

    In this noncompliant code example, the integer values 0 through 9 are expected to be printed to the standard output stream from a std::string rvalue reference. However, because the object is moved and then reused under the assumption its internal state has been cleared, unexpected output may occur despite not triggering undefined behavior.

    - #include <iostream> +
    +

    + In this noncompliant code example, the integer values + + 0 + + through + + 9 + + are expected to be printed to the standard output stream from a + + std::string + + rvalue reference. However, because theย object is moved and then reused under the assumption its internal state has been cleared, unexpected output may occur despite not triggering + + undefined behavior + + . +

    + + #include <iostream> #include <string> void g(std::string v) { @@ -208,10 +331,38 @@ void f() { s.append(1, static_cast<char>('0' + i)); g(std::move(s)); } -} -

    Implementation Details

    -

    Some standard library implementations may implement the short string optimization (SSO) when implementing std::string. In such implementations, strings under a certain length are stored in a character buffer internal to the std::string object (avoiding an expensive heap allocation operation). However, such an implementation might not alter the original buffer value when performing a move operation. When the noncompliant code example is compiled with Clang 3.7 using libc++, the following output is produced.

    - 0 +} + +

    + + Implementation Details + +

    +

    + Some standard library implementations may implement the + + short string optimization (SSO) + + when implementing + + std::string + + . In such implementations, strings under a certain length are stored in a character buffer internal to the + + std::string + + object (avoiding an expensive heap allocation operation). However, such an implementation might not alter the original buffer value when performing a move operation. When the noncompliant code example is compiled with + + Clang + + 3.7 using + + libc++ + + , the following output is produced. +

    + + 0 01 012 0123 @@ -220,11 +371,23 @@ void f() { 0123456 01234567 012345678 -0123456789 +0123456789 +
    -

    In this compliant solution, the std::string object is initialized to the expected value on each iteration of the loop. This practice ensures that the object is in a valid, specified state prior to attempting to access it in g(), resulting in the expected output.

    - #include <iostream> +

    + In this compliant solution, the + + std::string + + object is initialized to the expected value on each iteration of the loop. This practice ensures that the object is in a valid, specified state prior to attempting to access it in + + g() + + , resulting in the expected output. +

    + + #include <iostream> #include <string> void g(std::string v) { @@ -236,24 +399,44 @@ void f() { std::string s(1, static_cast<char>('0' + i)); g(std::move(s)); } -} +} +
    -
    -

    In this noncompliant code example, elements matching 42 are removed from the given container. The contents of the container are then printed to the standard output stream. However, if any elements were removed from the container, the range-based for loop iterates over an invalid iterator range, resulting in unspecified behavior.

    - #include <algorithm> +
    +

    + In this noncompliant code example, elements matching + + 42 + + are removed from the given container. The contents of the container are then printed to the standard output stream. However, if any elements were removed from the container, the range-based + + for + + loop iterates over an invalid iterator range, resulting in + + unspecified behavior + + . +

    + + #include <algorithm> #include <iostream> #include <vector> - +ย  void f(std::vector<int> &c) { std::remove(c.begin(), c.end(), 42); for (auto v : c) { std::cout << "Container element: " << v << std::endl; } -} +} +
    -

    In this compliant solution, elements removed by the standard algorithm are skipped during iteration.

    - #include <algorithm> +

    + In this compliant solution, elements removed by the standard algorithm are skipped during iteration. +

    + + #include <algorithm> #include <iostream> #include <vector> @@ -264,11 +447,19 @@ void f(std::vector<int> &c) { std::cout << *i << std::endl; } } -} +} +
    -

    In this compliant solution, elements removed by the standard algorithm are subsequently erased from the given container. This technique ensures that a valid iterator range is used by the range-based for loop.

    - #include <algorithm> +

    + In this compliant solution, elements removed by the standard algorithm are subsequently erased from the given container. This technique ensures that a valid iterator range is used by the range-based + + for + + loop. +

    + + #include <algorithm> #include <iostream> #include <vector> @@ -277,10 +468,13 @@ void f(std::vector<int> &c) { for (auto v : c) { std::cout << "Container element: " << v << std::endl; } -} +} +
    -

    The state of a moved-from object is generally valid, but unspecified. Relying on unspecified values can lead to abnormal program termination as well as data integrity violations.

    +

    + The state of a moved-from object is generally valid, but unspecified. Relying on unspecified values can lead to abnormal program termination as well as data integrity violations. +

    @@ -317,10 +511,14 @@ void f(std::vector<int> &c) { Medium @@ -343,22 +541,6 @@ void f(std::vector<int> &c) { Description - - - - - - @@ -384,7 +568,9 @@ void f(std::vector<int> &c) { 2021.2 @@ -427,7 +617,17 @@ void f(std::vector<int> &c) {
    - P8 + + P8 + - L2 + + L2 +
    - - CodeSonar - - - 6.2p0 - - LANG.MEM.NPD - - Null Pointer Dereference -
    @@ -369,7 +551,9 @@ void f(std::vector<int> &c) { 2021.2 - C++4701, C++4702, C++4703 + + C++4701, C++4702, C++4703 + - CERT_CPP-EXP63-a + + CERT_CPP-EXP63-a + Do not rely on the value of a moved-from object @@ -415,10 +601,14 @@ void f(std::vector<int> &c) { - 7.17 + 7.16 - V1030 + + + V1030 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -453,17 +653,23 @@ void f(std::vector<int> &c) { ]
    - Subclause 17.6.5.15, "Moved-from State of Library Types" + Subclauseย 17.6.5.15, "Moved-from State of Library Types" Subclause 20.8.1, "Class Template - unique_ptr + + unique_ptr + " Subclause 20.8.2, "Shared-Ownership Pointers" Subclause 27.5.5, "Class Template - basic_ios + + basic_ios + " Subclause 27.9.1, "File Streams" Subclause 30.3.1, "Class - thread + + thread + " Subclause 30.4.2, "Locks" Subclause 30.6, "Futures" diff --git a/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition-standard.qhelp b/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition-standard.qhelp index e8c3ca4ff4..9943e7d2b1 100644 --- a/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition-standard.qhelp +++ b/cpp/cert/src/rules/FIO50-CPP/InterleavedInputOutputWithoutPosition-standard.qhelp @@ -1,25 +1,138 @@
    -

    The C++ Standard, [filebuf], paragraph 2 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [filebuf], paragraph 2 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf<charT, traits> are the same as for reading and writing with the Standard C library FILEs.

    +

    + The restrictions on reading and writing a sequence controlled by an object of class + + basic_filebuf<charT,ย traits> + + are the same as for reading and writing with the Standard C library + + FILE + + s. +

    -

    The C Standard, subclause 7.19.5.3, paragraph 6 [ISO/IEC 9899:1999], places the following restrictions on FILE objects opened for both reading and writing:

    +

    + The C Standard, subclause 7.19.5.3, paragraph 6ย [ + + ISO/IEC 9899:1999 + + ], places the following restrictions on + + FILE + + objects opened for both reading and writing: +

    -

    When a file is opened with update mode . . ., both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.

    +

    + When a file is opened with update mode . . .,ย both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the + + fflush + + function or to a file positioning function ( + + fseek + + , + + fsetpos + + , or + + rewind + + ), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file. +

    -

    Consequently, the following scenarios can result in undefined behavior:

    +

    + Consequently, the following scenarios can result in + + undefined behavior + + : +

      -
    • Receiving input from a stream directly following an output to that stream without an intervening call to std::basic_filebuf<T>::seekoff() if the file is not at end-of-file
    • -
    • Outputting to a stream after receiving input from that stream without a call to std::basic_filebuf<T>::seekoff() if the file is not at end-of-file
    • +
    • + Receiving input from a stream directly following an output to that stream without an intervening call to + + std::basic_filebuf<T>::seekoff() + + if the file is not at end-of-file +
    • +
    • + Outputting to a stream after receiving input from that stream without a call to + + std::basic_filebuf<T>::seekoff() + + if the file is not at end-of-file +
    -

    No other std::basic_filebuf<T> function guarantees behavior as if a call were made to a standard C library file-positioning function, or std::fflush().

    -

    Calling std::basic_ostream<T>::seekp() or std::basic_istream<T>::seekg() eventually results in a call to std::basic_filebuf<T>::seekoff() for file stream positioning. Given that std::basic_iostream<T> inherits from both std::basic_ostream<T> and std::basic_istream<T>, and std::fstream inherits from std::basic_iostream, either function is acceptable to call to ensure the file buffer is in a valid state before the subsequent I/O operation.

    +

    + No other + + std::basic_filebuf<T> + + function guarantees behavior as if a call were made to a standard C library file-positioning function, or + + std::fflush() + + . +

    +

    + Calling + + std::basic_ostream<T>::seekp() + + or + + std::basic_istream<T>::seekg() + + eventually results in a call to + + std::basic_filebuf<T>::seekoff() + + for file stream positioning. Given that + + std::basic_iostream<T> + + inherits from both + + std::basic_ostream<T> + + and + + std::basic_istream<T> + + , and + + std::fstream + + inherits from + + std::basic_iostream + + , either function is acceptable to call to ensure the file buffer is in a valid state before the subsequent I/O operation. +

    -

    This noncompliant code example appends data to the end of a file and then reads from the same file. However, because there is no intervening positioning call between the formatted output and input calls, the behavior is undefined.

    - #include <fstream> +

    + This noncompliant code example appends data to the end of a file and then reads from the same file. However, because there is no intervening positioning call between the formatted output and input calls, the behavior is + + undefined + + . +

    + + #include <fstream> #include <string> void f(const std::string &fileName) { @@ -33,11 +146,22 @@ void f(const std::string &fileName) { std::string str; file >> str; } - +
    -

    In this compliant solution, the std::basic_istream<T>::seekg() function is called between the output and input, eliminating the undefined behavior.

    - #include <fstream> +

    + In this compliant solution, the + + std::basic_istream<T>::seekg() + + function is called between the output and input, eliminating the + + undefined behavior + + . +

    + + #include <fstream> #include <string> void f(const std::string &fileName) { @@ -48,15 +172,21 @@ void f(const std::string &fileName) { } file << "Output some data"; - +ย  std::string str; file.seekg(0, std::ios::beg); file >> str; } - +
    -

    Alternately inputting and outputting from a stream without an intervening flush or positioning call is undefined behavior.

    +

    + Alternately inputting and outputting from a stream without an intervening flush or positioning call is + + undefined behavior + + . +

    @@ -93,10 +223,14 @@ void f(const std::string &fileName) { Medium @@ -129,29 +263,13 @@ void f(const std::string &fileName) { 7.2.0 - - - - - - @@ -177,7 +297,9 @@ void f(const std::string &fileName) { 2021.2
    - P6 + + P6 + - L2 + + L2 +
    - CertC++-FIO50 + + CertC++-FIO50 +
    - - CodeSonar - - - 6.2p0 - - IO.IOWOP - IO.OIWOP - - Input After Output Without Positioning - Output After Input Without Positioning -
    @@ -162,7 +280,9 @@ void f(const std::string &fileName) { 2021.2 - C++4711, C++4712, C++4713 + + C++4711, C++4712, C++4713 + - CERT_CPP-FIO50-a + + CERT_CPP-FIO50-a + Do not alternately input and output from a stream without an intervening flush or positioning call @@ -205,10 +327,30 @@ void f(const std::string &fileName) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule supplements FIO39-C. Do not alternately input and output from a stream without an intervening flush or positioning call.

    +

    + + This rule supplements + + + + FIO39-C. Do not alternately input and output from a stream without an intervening flush or positioning call + + . + +

    @@ -233,7 +375,9 @@ void f(const std::string &fileName) { diff --git a/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp b/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp index ad1167f071..f77907f31f 100644 --- a/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp +++ b/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded-standard.qhelp @@ -1,12 +1,87 @@
    -

    A call to the std::basic_filebuf<T>::open() function must be matched with a call to std::basic_filebuf<T>::close() before the lifetime of the last pointer that stores the return value of the call has ended or before normal program termination, whichever occurs first.

    -

    Note that std::basic_ifstream<T>, std::basic_ofstream<T>, and std::basic_fstream<T> all maintain an internal reference to a std::basic_filebuf<T> object on which open() and close() are called as needed. Properly managing an object of one of these types (by not leaking the object) is sufficient to ensure compliance with this rule. Often, the best solution is to use the stream object by value semantics instead of via dynamic memory allocation, ensuring compliance with MEM51-CPP. Properly deallocate dynamically allocated resources. However, that is still insufficient for situations in which destructors are not automatically called.

    +

    + A call to the + + std::basic_filebuf<T>::open() + + function must be matched with a call to + + std::basic_filebuf<T>::close() + + before the lifetime of the last pointer that stores the return value of the call has ended or before normal program termination, whichever occurs first. +

    +

    + Note that + + std::basic_ifstream<T> + + , + + std::basic_ofstream<T> + + , and + + std::basic_fstream<T> + + all maintain an internal reference to a + + std::basic_filebuf<T> + + object on which + + open() + + and + + close() + + are called as needed. Properly managing an object of one of these types (by not leaking the object) is sufficient to ensure compliance with this rule. Often, the best solution is to use the stream object by value semantics instead of via dynamic memory allocation, ensuring compliance with + + MEM51-CPP. Properly deallocate dynamically allocated resources + + . However, that is still insufficient for situations in which destructors are not automatically called. +

    -

    In this noncompliant code example, a std::fstream object file is constructed. The constructor for std::fstream calls std::basic_filebuf<T>::open(), and the default std::terminate_handler called by std::terminate() is std::abort(), which does not call destructors. Consequently, the underlying std::basic_filebuf<T> object maintained by the object is not properly closed.

    - #include <exception> +

    + In this noncompliant code example, a + + std::fstream + + object + + file + + is constructed. The constructor for + + std::fstream + + calls + + std::basic_filebuf<T>::open() + + , and the default + + std::terminate_handler + + called by + + std::terminate() + + is + + std::abort() + + , which does not call destructors. Consequently, the underlying + + std::basic_filebuf<T> + + object maintained by the object is not properly closed. +

    + + #include <exception> #include <fstream> #include <string> @@ -18,12 +93,34 @@ void f(const std::string &fileName) { } // ... std::terminate(); -} -

    This noncompliant code example and the subsequent compliant solutions are assumed to eventually call std::terminate() in accordance with the ERR50-CPP-EX1 exception described in ERR50-CPP. Do not abruptly terminate the program. Indicating the nature of the problem to the operator is elided for brevity.

    +} +
    +

    + This noncompliant code example and the subsequent compliant solutions are assumed to eventually call + + std::terminate() + + in accordance with the ERR50-CPP-EX1 exception described in + + ERR50-CPP. Do not abruptly terminate the program + + . Indicating the nature of the problem to the operator is elided for brevity. +

    -

    In this compliant solution, std::fstream::close() is called before std::terminate() is called, ensuring that the file resources are properly closed.

    - #include <exception> +

    + In this compliant solution, + + std::fstream::close() + + is called before + + std::terminate() + + is called, ensuring that the file resources are properly closed. +

    + + #include <exception> #include <fstream> #include <string> @@ -40,11 +137,22 @@ void f(const std::string &fileName) { } std::terminate(); } - +
    -

    In this compliant solution, the stream is implicitly closed through RAII before std::terminate() is called, ensuring that the file resources are properly closed.

    - #include <exception> +

    + In this compliant solution, the stream is implicitly closed through + + RAII + + before + + std::terminate() + + is called, ensuring that the file resources are properly closed. +

    + + #include <exception> #include <fstream> #include <string> @@ -57,10 +165,17 @@ void f(const std::string &fileName) { } } // file is closed properly here when it is destroyed std::terminate(); -} +} +
    -

    Failing to properly close files may allow an attacker to exhaust system resources and can increase the risk that data written into in-memory file buffers will not be flushed in the event of abnormal program termination.

    +

    + Failing to properly close files may allow an attacker to exhaust system resources and can increase the risk that data written into in-memory file buffers will not be flushed in the event of + + abnormal program termination + + . +

    Subclause 7.19.5.3, "The - fopen + + fopen + Function"
    @@ -97,10 +212,14 @@ void f(const std::string &fileName) { Medium @@ -130,10 +249,12 @@ void f(const std::string &fileName) { @@ -164,7 +287,11 @@ void f(const std::string &fileName) { 2021.4 @@ -179,7 +306,9 @@ void f(const std::string &fileName) { 2021.2
    - P4 + + P4 + - L3 + + L3 +
    - 6.2p0 + 6.1p0 - ALLOC.LEAK + + ALLOC.LEAK + Leak @@ -149,7 +270,9 @@ void f(const std::string &fileName) { 2021.2 - C++4786, C++4787, C++4788 + + C++4786, C++4787, C++4788 + - RH.LEAK + + + RH.LEAK + + - CERT_CPP-FIO51-a + + CERT_CPP-FIO51-a + Ensure resources are freed @@ -221,10 +350,28 @@ void f(const std::string &fileName) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule supplements FIO42-C. Close files when they are no longer needed.

    +

    + + This rule supplements + + FIO42-C. Close files when they are no longer needed + + . + +

    diff --git a/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql b/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql index d7436c748b..8736348682 100644 --- a/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql +++ b/cpp/cert/src/rules/FIO51-CPP/CloseFilesWhenTheyAreNoLongerNeeded.ql @@ -12,7 +12,7 @@ */ import cpp -import codingstandards.cpp.Exclusions +import codingstandards.cpp.cert import codingstandards.cpp.standardlibrary.CStdLib import codingstandards.cpp.standardlibrary.FileStreams import codingstandards.cpp.standardlibrary.Exceptions @@ -36,7 +36,8 @@ predicate filebufAccess(ControlFlowNode node, FileStreamSource fss) { node = fss or node.(OpenFunctionCall).getFStream() = fss.getAUse() or //insertion or extraction operator calls - node.(InExOperatorCall).getFStream() = fss.getAUse() or + node.(InsertionOperatorCall).getFStream() = fss.getAUse() or + node.(ExtractionOperatorCall).getFStream() = fss.getAUse() or //methods inherited from istream or ostream node.(IOStreamFunctionCall).getFStream() = fss.getAUse() } diff --git a/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue-standard.qhelp b/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue-standard.qhelp index e849086aa5..6d8f724edd 100644 --- a/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue-standard.qhelp +++ b/cpp/cert/src/rules/INT50-CPP/DoNotCastToAnOutOfRangeEnumerationValue-standard.qhelp @@ -1,19 +1,78 @@
    -

    Enumerations in C++ come in two forms: scoped enumerations in which the underlying type is fixed and unscoped enumerations in which the underlying type may or may not be fixed. The range of values that can be represented by either form of enumeration may include enumerator values not specified by the enumeration itself. The range of valid enumeration values for an enumeration type is defined by the C++ Standard, [dcl.enum], in paragraph 8 [ISO/IEC 14882-2020]:

    +

    + Enumerations in C++ come in two forms: + + scoped + + enumerations in which the underlying type is fixed and + + unscoped + + enumerations in which the underlying type may or may not be fixed. The range of values that can be represented by either form of enumeration may include enumerator values not specified by the enumeration itself.ย The range of valid enumeration values for an enumeration type is defined by the C++ Standard, [dcl.enum], in paragraph 8 [ + + ISO/IEC 14882-2020 + + ]: +

    -

    For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width M such that all enumerators can be represented. The width of the smallest bit-field large enough to hold all the values of the enumeration type is M. It is possible to define an enumeration that has values not defined by any of its enumerators. If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.

    +

    + For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width + M + such that all enumerators can be represented. The width of the smallest bit-field large enough to hold all the values of the enumeration type is + M + . It is possible to define an enumeration that has values not defined by any of its enumerators. If the + enumerator-list + is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0. +

    -

    The C++ Standard, [expr.static.cast], paragraph 10, states the following:

    +

    + The C++ Standard, [expr.static.cast], paragraph 10, states the following: +

    -

    A value of integral or enumeration type can be explicitly converted to a complete enumeration type. If the enumeration type has a fixed underlying type, the value is first converted to that type by integral conversion, if necessary, and then to the enumeration type. If the enumeration type does not have a fixed underlying type, the value is unchanged if the original value is within the range of the enumeration values (9.7.1), and otherwise, the behavior is undefined. A value of floating-point type can also be explicitly converted to an enumeration type. The resulting value is the same as converting the original value to the underlying type of the enumeration (7.3.10), and subsequently to the enumeration type.

    +

    + A value of integral or enumeration type can be explicitly converted to a complete enumeration type. If the enumeration type has a fixed underlying type, the value is first converted to that type by integral conversion, if necessary, and then to the enumeration type. If the enumeration type does not have a fixed underlying type, the value is unchanged if the original value is within the range of the enumeration values ( + 9.7.1 + ), and otherwise, the behavior is undefined. A value of floating-point type can also be explicitly converted to an enumeration type. The resulting value is the same as converting the original value to the underlying type of the enumeration ( + 7.3.10 + ), and subsequently to the enumeration type. +

    -

    To avoid operating on unspecified values, the arithmetic value being cast must be within the range of values the enumeration can represent. When dynamically checking for out-of-range values, checking must be performed before the cast expression.

    +

    + To avoid operating on + + unspecified values + + , the arithmetic value being cast must be within the range of values the enumeration can represent. When dynamically checking for out-of-range values, checking must be performed before the cast expression. +

    -

    This noncompliant code example attempts to check whether a given value is within the range of acceptable enumeration values. However, it is doing so after casting to the enumeration type, which may not be able to represent the given integer value. On a two's complement system, the valid range of values that can be represented by EnumType are [0..3], so if a value outside of that range were passed to f(), the cast to EnumType would result in an unspecified value, and using that value within the if statement results in unspecified behavior.

    - enum EnumType { +

    + This noncompliant code example attempts to check whether a given value is within the range of acceptable enumeration values.ย However, it is doing so after casting to the enumeration type, which may not be able to represent the given integer value. On a two's complement system, the valid range of values that can be represented by + + EnumType + + are [0..3], so if a value outside of that range were passed to + + f() + + , theย cast to + + EnumType + + would result in an unspecified value, and using that value within the + + if + + statement results in + + unspecified behavior + + . +

    + + enum EnumType { First, Second, Third @@ -25,11 +84,15 @@ void f(int intVar) { if (enumVar < First || enumVar > Third) { // Handle error } -} +} +
    -

    This compliant solution checks that the value can be represented by the enumeration type before performing the conversion to guarantee the conversion does not result in an unspecified value. It does this by restricting the converted value to one for which there is a specific enumerator value.

    - enum EnumType { +

    + This compliant solution checks that the value can be represented by the enumeration type before performing the conversion to guarantee the conversion does not result in an unspecified value. It does this by restricting the converted value to one for which there is a specific enumerator value. +

    + + enum EnumType { First, Second, Third @@ -41,11 +104,18 @@ void f(int intVar) { } EnumType enumVar = static_cast<EnumType>(intVar); } - +
    -

    This compliant solution uses a scoped enumeration, which has a fixed underlying int type by default, allowing any value from the parameter to be converted into a valid enumeration value. It does not restrict the converted value to one for which there is a specific enumerator value, but it could do so as shown in the previous compliant solution.

    - enum class EnumType { +

    + This compliant solution uses a scoped enumeration, which has a fixed underlying + + int + + type by default, allowing any value from the parameter to be converted into a valid enumeration value. It does not restrict the converted value to one for which there is a specific enumerator value, but it could do so as shown in the previous compliant solution. +

    + + enum class EnumType { First, Second, Third @@ -53,11 +123,19 @@ void f(int intVar) { void f(int intVar) { EnumType enumVar = static_cast<EnumType>(intVar); -} +} +
    -

    Similar to the previous compliant solution, this compliant solution uses an unscoped enumeration but provides a fixed underlying int type allowing any value from the parameter to be converted to a valid enumeration value.

    - enum EnumType : int { +

    + Similar to the previous compliant solution, this compliant solution uses an unscoped enumeration but provides a fixed underlying + + int + + type allowing any value from the parameter to be converted to a valid enumeration value. +

    + + enum EnumType : int { First, Second, Third @@ -65,11 +143,28 @@ void f(int intVar) { void f(int intVar) { EnumType enumVar = static_cast<EnumType>(intVar); -} -

    Although similar to the previous compliant solution, this compliant solution differs from the noncompliant code example in the way the enumerator values are expressed in code and which implicit conversions are allowed. The previous compliant solution requires a nested name specifier to identify the enumerator (for example, EnumType::First) and will not implicitly convert the enumerator value to int. As with the noncompliant code example, this compliant solution does not allow a nested name specifier and will implicitly convert the enumerator value to int.

    +} +
    +

    + Although similar to the previous compliant solution, this compliant solution differs from the noncompliant code example in the way the enumerator values are expressed in code and which implicit conversions are allowed. The previous compliant solution requires a nested name specifier to identify the enumerator (for example, + + EnumType::First + + ) and will not implicitly convert the enumerator value to + + int + + . As with the noncompliant code example, this compliant solution does not allow a nested name specifier and will implicitly convert the enumerator value to + + int + + . +

    -

    It is possible for unspecified values to result in a buffer overflow, leading to the execution of arbitrary code by an attacker. However, because enumerators are rarely used for indexing into arrays or other forms of pointer arithmetic, it is more likely that this scenario will result in data integrity violations rather than arbitrary code execution.

    +

    + It is possible for unspecified values to result in a buffer overflow, leading to the execution of arbitrary code by an attacker. However, because enumerators are rarely used for indexing into arrays or other forms of pointer arithmetic, it is more likely that this scenario will result in data integrity violations rather than arbitrary code execution. +

    @@ -106,10 +201,14 @@ void f(int intVar) { Medium @@ -142,27 +241,11 @@ void f(int intVar) { 7.2.0 - - - - - - @@ -175,7 +258,10 @@ void f(int intVar) { 2021.2 @@ -190,7 +276,9 @@ void f(int intVar) { 2021.2 @@ -218,10 +308,14 @@ void f(int intVar) { @@ -230,7 +324,17 @@ void f(int intVar) {
    - P4 + + P4 + - L3 + + L3 +
    - CertC++-INT50 - -
    - - CodeSonar - - - 6.2p0 - - LANG.CAST.COERCE - LANG.CAST.VALUE + + CertC++-INT50 + - Coercion Alters Value - Cast Alters Value
    - C++3013 + + C++ + 3013 + - CERT_CPP-INT50-a + + CERT_CPP-INT50-a + An expression with enum underlying type shall only have values corresponding to the enumerators of the enumeration @@ -206,7 +294,9 @@ void f(int intVar) { 4.4 - 3013 + + 3013 + - 7.17 + 7.16 - V1016 + + + V1016 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM50-CPP/UseAfterFree-standard.qhelp b/cpp/cert/src/rules/MEM50-CPP/UseAfterFree-standard.qhelp index ce87a52e92..1a7feb63fe 100644 --- a/cpp/cert/src/rules/MEM50-CPP/UseAfterFree-standard.qhelp +++ b/cpp/cert/src/rules/MEM50-CPP/UseAfterFree-standard.qhelp @@ -1,17 +1,48 @@
    -

    Evaluating a pointerโ€”including dereferencing the pointer, using it as an operand of an arithmetic operation, type casting it, and using it as the right-hand side of an assignmentโ€”into memory that has been deallocated by a memory management function is undefined behavior. Pointers to memory that has been deallocated are called dangling pointers. Accessing a dangling pointer can result in exploitable vulnerabilities.

    -

    It is at the memory manager's discretion when to reallocate or recycle the freed memory. When memory is freed, all pointers into it become invalid, and its contents might either be returned to the operating system, making the freed space inaccessible, or remain intact and accessible. As a result, the data at the freed location can appear to be valid but change unexpectedly. Consequently, memory must not be written to or read from once it is freed.

    +

    + Evaluating a pointerโ€”including dereferencing the pointer, using it as an operand of an arithmetic operation, type casting it, and using it as the right-hand side of an assignmentโ€”into memory that has been deallocated by a memory management function is + + undefined behavior + + . Pointers to memory that has been deallocated are called + + dangling pointers + + . Accessing a dangling pointer can result in exploitable + + vulnerabilities + + . +

    +

    + It is at the memory manager's discretion when to reallocate or recycle the freed memory. When memory is freed, all pointers into it become invalid, and its contents might either be returned to the operating system, making the freed space inaccessible, or remain intact and accessible. As a result, the data at the freed location can appear to be valid but change unexpectedly. Consequently, memory must not be written to or read from once it is freed. +

    -
    -

    In this noncompliant code example, s is dereferenced after it has been deallocated. If this access results in a write-after-free, the vulnerability can be exploited to run arbitrary code with the permissions of the vulnerable process. Typically, dynamic memory allocations and deallocations are far removed, making it difficult to recognize and diagnose such problems.

    - #include <new> - +
    +

    + In this noncompliant code example, + + s + + is dereferenced after it has been deallocated. If this access results in a write-after-free, the + + vulnerability + + can be + + exploited + + to run arbitrary code with the permissions of the vulnerable process.ย Typically, dynamic memory allocations and deallocations are far removed, making it difficult to recognize and diagnose such problems. +

    + + #include <new> +ย  struct S { void f(); }; - +ย  void g() noexcept(false) { S *s = new S; // ... @@ -19,12 +50,29 @@ void g() noexcept(false) { // ... s->f(); } - -

    The function g() is marked noexcept(false) to comply with MEM52-CPP. Detect and handle memory allocation errors.

    + +

    + The function + + g() + + is marked + + noexcept(false) + + to comply with + + MEM52-CPP. Detect and handle memory allocation errors + + . +

    -
    -

    In this compliant solution, the dynamically allocated memory is not deallocated until it is no longer required.

    - #include <new> +
    +

    + In this compliant solution, the dynamically allocated memory is not deallocated until it is no longer required. +

    + + #include <new> struct S { void f(); @@ -35,11 +83,30 @@ void g() noexcept(false) { // ... s->f(); delete s; -} +} +
    -

    When possible, use automatic storage duration instead of dynamic storage duration. Since s is not required to live beyond the scope of g(), this compliant solution uses automatic storage duration to limit the lifetime of s to the scope of g().

    - struct S { +

    + When possible, use automatic storage duration instead of dynamic storage duration. Since + + s + + is not required to live beyond the scope of + + g() + + , this compliant solution uses automatic storage duration to limit the lifetime of + + s + + to the scope of + + g(). + +

    + + struct S { void f(); }; @@ -47,14 +114,22 @@ void g() { S s; // ... s.f(); -} +} +
    -

    In the following noncompliant code example, the dynamically allocated memory managed by the buff object is accessed after it has been implicitly deallocated by the object's destructor.

    - #include <iostream> +

    + In the following noncompliant code example, the dynamically allocated memory managed by the + + buff + + object is accessed after it has been implicitly deallocated by the object's destructor. +

    + + #include <iostream> #include <memory> #include <cstring> - +ย  int main(int argc, const char *argv[]) { const char *s = ""; if (argc > 1) { @@ -71,15 +146,32 @@ int main(int argc, const char *argv[]) { std::cout << s << std::endl; } - -

    This code always creates a null-terminated byte string, despite its use of strncpy(), because it leaves the final char in the buffer set to 0.

    +
    +

    + This code always creates a null-terminated byte string, despite its use of + + strncpy() + + , because it leaves the final + + char + + in the buffer set to 0. +

    -

    In this compliant solution, the lifetime of the buff object extends past the point at which the memory managed by the object is accessed.

    - #include <iostream> +

    + In this compliant solution, the lifetime of the + + buff + + object extends past the point at which the memory managed by the object is accessed. +

    + + #include <iostream> #include <memory> #include <cstring> - +ย  int main(int argc, const char *argv[]) { std::unique_ptr<char[]> buff; const char *s = ""; @@ -98,13 +190,24 @@ int main(int argc, const char *argv[]) { std::cout << s << std::endl; } - +
    -

    In this compliant solution, a variable with automatic storage duration of type std::string is used in place of the std::unique_ptr<char[]>, which reduces the complexity and improves the security of the solution.

    - #include <iostream> +

    + In this compliant solution, a variable with automatic storage durationย of type + + std::string + + is used in place of the + + std::unique_ptr<char[]> + + , which reduces the complexity and improvesย the security of the solution. +

    + + #include <iostream> #include <string> - +ย  int main(int argc, const char *argv[]) { std::string str; @@ -113,24 +216,60 @@ int main(int argc, const char *argv[]) { } std::cout << str << std::endl; -} +} +
    -

    In this noncompliant code example, std::string::c_str() is being called on a temporary std::string object. The resulting pointer will point to released memory once the std::string object is destroyed at the end of the assignment expression, resulting in undefined behavior when accessing elements of that pointer.

    - #include <string> - +

    + In this noncompliant code example, + + std::string::c_str() + + is being called on a temporary + + std::string + + object. The resulting pointer will point to released memory once the + + std::string + + object is destroyed at the end of the assignment expression, resulting in + + undefined behavior + + when accessing elements of that pointer. +

    + + #include <string> +ย  std::string str_func(); void display_string(const char *); - +ย  void f() { const char *str = str_func().c_str(); display_string(str); /* Undefined behavior */ -} +} +
    -

    In this compliant solution, a local copy of the string returned by str_func() is made to ensure that string str will be valid when the call to display_string() is made.

    - #include <string> - +

    + In this compliant solution, a local copy of the string returned by + + str_func() + + is made to ensure that string + + str + + will be valid when the call to + + display_string() + + is made. +

    + + #include <string> +ย  std::string str_func(); void display_string(const char *s); @@ -138,40 +277,106 @@ void f() { std::string str = str_func(); const char *cstr = str.c_str(); display_string(cstr); /* ok */ -} +} +
    -

    In this noncompliant code example, an attempt is made to allocate zero bytes of memory through a call to operator new(). If this request succeeds, operator new() is required to return a non-null pointer value. However, according to the C++ Standard, [basic.stc.dynamic.allocation], paragraph 2 [ISO/IEC 14882-2014], attempting to dereference memory through such a pointer results in undefined behavior.

    - #include <new> +

    + In this noncompliant code example, an attempt is made to allocate zero bytes of memory through a call to + + operator new() + + . If this request succeeds, + + operator new() + + is required to return a non-null pointer value. However, according to the C++ Standard,ย [basic.stc.dynamic.allocation], paragraph 2 [ + + ISO/IEC 14882-2014 + + ], attempting to dereference memory through such a pointer results in + + undefined behavior + + . +

    + + #include <new> void f() noexcept(false) { unsigned char *ptr = static_cast<unsigned char *>(::operator new(0)); *ptr = 0; // ... ::operator delete(ptr); -} +} +
    -

    The compliant solution depends on programmer intent. If the programmer intends to allocate a single unsigned char object, the compliant solution is to use new instead of a direct call to operator new(), as this compliant solution demonstrates.

    - void f() noexcept(false) { +

    + The compliant solution depends on programmer intent. If the programmer intends to allocate a single + + unsigned char + + object, the compliant solution is to use + + new + + instead of a direct call to + + operator new() + + , as this compliant solution demonstrates. +

    + + void f() noexcept(false) { unsigned char *ptr = new unsigned char; *ptr = 0; // ... delete ptr; -} +} +
    -

    If the programmer intends to allocate zero bytes of memory (perhaps to obtain a unique pointer value that cannot be reused by any other pointer in the program until it is properly released), then instead of attempting to dereference the resulting pointer, the recommended solution is to declare ptr as a void *, which cannot be dereferenced by a conforming implementation.

    - #include <new> +

    + If the programmer intends to allocate zero bytes of memory (perhaps to obtain a unique pointer value that cannot be reused by any other pointer in the program until it is properly released), then instead of attempting to dereference the resulting pointer, the recommended solution is to declare + + ptr + + as a + + void * + + , which cannot be dereferenced by a + + conforming + + + implementation + + . +

    + + #include <new> void f() noexcept(false) { void *ptr = ::operator new(0); // ... ::operator delete(ptr); -} +} +
    -

    Reading previously dynamically allocated memory after it has been deallocated can lead to abnormal program termination and denial-of-service attacks. Writing memory that has been deallocated can lead to the execution of arbitrary code with the permissions of the vulnerable process.

    +

    + Reading previously dynamically allocated memory after it has been deallocated can lead to + + abnormal program termination + + and + + denial-of-service attacks + + . Writing memory that has been deallocated can lead to the execution of arbitrary code with the permissions of the vulnerable process. +

    @@ -208,10 +413,14 @@ void f() noexcept(false) { Medium @@ -244,7 +453,9 @@ void f() noexcept(false) { 20.10 @@ -259,7 +470,9 @@ void f() noexcept(false) { 7.2.0 @@ -274,11 +487,16 @@ void f() noexcept(false) { 3.9 @@ -289,10 +507,12 @@ void f() noexcept(false) { @@ -337,7 +559,9 @@ void f() noexcept(false) { 2021.2 @@ -352,14 +576,46 @@ void f() noexcept(false) { 2021.4 @@ -373,7 +629,9 @@ void f() noexcept(false) { @@ -439,7 +699,9 @@ void f() noexcept(false) { 4.4 @@ -451,12 +713,20 @@ void f() noexcept(false) { @@ -478,8 +748,28 @@ void f() noexcept(false) {
    - P18 + + P18 + - L1 + + L1 +
    - dangling_pointer_use + + dangling_pointer_use + - CertC++-MEM50 + + CertC++-MEM50 + - clang-analyzer-cplusplus.NewDeleteclang-analyzer-alpha.security.ArrayBoundV2 + + clang-analyzer-cplusplus.NewDelete + clang-analyzer-alpha.security.ArrayBoundV2 + Checked by - clang-tidy + + clang-tidy + , but does not catch all violations of this rule.
    - 6.2p0 + 6.1p0 - ALLOC.UAF + + ALLOC.UAF + Use after free @@ -321,10 +541,12 @@ void f() noexcept(false) { v7.5.0 - USE_AFTER_FREE + + USE_AFTER_FREE + - Can detect the specific instances where memory is deallocated more than once or read/written to the target of a freed pointer + Can detect the specific instances where memory is deallocated more than once or read/writtenย to the target of a freed pointer
    - C++4303, C++4304 + + C++4303, C++4304 + - UFM.DEREF.MIGHT - UFM.DEREF.MUST - UFM.FFM.MIGHT - UFM.FFM.MUST - UFM.RETURN.MIGHT - UFM.RETURN.MUST - UFM.USE.MIGHT - UFM.USE.MUST + + + UFM.DEREF.MIGHT + + + + + UFM.DEREF.MUST + + + + + UFM.FFM.MIGHT + + + + + UFM.FFM.MUST + + + + + UFM.RETURN.MIGHT + + + + + UFM.RETURN.MUST + + + + + UFM.USE.MIGHT + + + + + UFM.USE.MUST + + - 483 S, 484 S + + 483 S, 484 S + Partially implemented @@ -389,7 +647,9 @@ void f() noexcept(false) { 2021.2 - CERT_CPP-MEM50-a + + CERT_CPP-MEM50-a + Do not use resources that have been freed @@ -425,7 +685,7 @@ void f() noexcept(false) { Checks for: - Pointer access out of boundsointer access out of bounds, deallocation of previously deallocated pointereallocation of previously deallocated pointer, use of previously freed pointerse of previously freed pointer. + Pointer access out of bounds, deallocation of previously deallocated pointer, use of previously freed pointer. Rule partially covered.
    - 4303, 4304 + + 4303, 4304 + - 7.17 + 7.16 - V586 + + V586 + + + , - V774 + + + V774 + +
    -

    VU#623332 describes a double-free vulnerability in the MIT Kerberos 5 function krb5_recvauth() [VU# 623332].

    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + VU#623332ย describes a double-free vulnerability in the MIT Kerberos 5 function + + krb5_recvauth() + + [ + + VU# 623332 + + ]. +

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql b/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql index ce570157de..59bf3e5bc7 100644 --- a/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql +++ b/cpp/cert/src/rules/MEM50-CPP/UseAfterFree.ql @@ -16,7 +16,5 @@ import codingstandards.cpp.cert import codingstandards.cpp.rules.objectaccessedafterlifetime.ObjectAccessedAfterLifetime class ObjectAccessedAfterLifetimeCertQuery extends ObjectAccessedAfterLifetimeSharedQuery { - ObjectAccessedAfterLifetimeCertQuery() { - this = FreedPackage::useAfterFreeQuery() - } + ObjectAccessedAfterLifetimeCertQuery() { this = FreedPackage::useAfterFreeQuery() } } diff --git a/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources-standard.qhelp b/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources-standard.qhelp index ed4541aee0..00b52e5ae2 100644 --- a/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources-standard.qhelp +++ b/cpp/cert/src/rules/MEM51-CPP/ProperlyDeallocateDynamicallyAllocatedResources-standard.qhelp @@ -1,9 +1,67 @@
    -

    The C programming language provides several ways to allocate memory, such as std::malloc(), std::calloc(), and std::realloc(), which can be used by a C++ program. However, the C programming language defines only a single way to free the allocated memory: std::free(). See MEM31-C. Free dynamically allocated memory when no longer needed and MEM34-C. Only free memory allocated dynamically for rules specifically regarding C allocation and deallocation requirements.

    -

    The C++ programming language adds additional ways to allocate memory, such as the operators new, new[], and placement new, and allocator objects. Unlike C, C++ provides multiple ways to free dynamically allocated memory, such as the operators delete, delete[](), and deallocation functions on allocator objects.

    -

    Do not call a deallocation function on anything other than nullptr , or a pointer returned by the corresponding allocation function described by the following.

    +

    + The C programming language provides several ways to allocate memory, such as + + std::malloc() + + , + + std::calloc() + + , and + + std::realloc() + + , which can be used by a C++ program. However, the C programming language defines only a single way to free the allocated memory: + + std::free() + + . See + + MEM31-C. Free dynamically allocated memory when no longer needed + + and + + MEM34-C. Only free memory allocated dynamically + + for rules specifically regarding C allocation and deallocation requirements. +

    +

    + The C++ programming language adds additional ways to allocate memory, such as the operators + + new + + , + + new[] + + , and placement + + new + + , and + + allocator objects + + . Unlike C, C++ provides multiple ways to free dynamically allocated memory, such as the operators + + delete + + , + + delete[]() + + , and deallocation functions on allocator objects. +

    +

    + Do not call a deallocation function on anything other than + + nullptr + + , or a pointer returned by the corresponding allocation function described by the following. +

    @@ -17,51 +75,73 @@
    global - operator new()/new + + operator new()/new + global - operator delete + + operator delete + () - /delete + + /delete +
    global - operator new[]()/new[] + + operator new[]()/new[] + global - operator delete[]()/delete[] + + operator delete[]()/delete[] +
    class-specific - operator new()/new + + operator new()/new + -class-specific operator delete + class-specific + operator delete + () - /delete + + /delete +
    -class-specific operator new[]()/new[] + class-specific + operator new[]()/new[] + -class-specific operator delete[]()/delete[] + class-specific + operator delete[]()/delete[] +
    placement - operator new + + operator new + () @@ -70,49 +150,169 @@ class-specific operator delete[]()/delete[]
    - allocator<T>::allocate() + + allocator<T>::allocate() + - allocator<T>::deallocate() + + allocator<T>::deallocate() +
    - std::malloc() + + std::malloc() + , - std::calloc() + + std::calloc() + , -std::realloc() + std:: + realloc() + -std::free() + std:: + free() +
    - std::get_temporary_buffer() + + std::get_temporary_buffer() + - std::return_temporary_buffer() + + std::return_temporary_buffer() +
    -

    Passing a pointer value to an inappropriate deallocation function can result in undefined behavior.

    -

    The C++ Standard, [expr.delete], paragraph 2 [ISO/IEC 14882-2014], in part, states the following:

    +

    + Passing a pointer value to an inappropriate deallocation function can result in + + undefined behavior + + . +

    +

    + The C++ Standard, [expr.delete], paragraph 2 [ + + ISO/IEC 14882-2014 + + ], in part, states the following: +

    -

    In the first alternative (delete object), the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject (1.8) representing a base class of such an object (Clause 10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression. If not, the behavior is undefined.

    +

    + In the first alternative ( + + delete object + + ), the value of the operand of + + delete + + may be a null pointerย value, a pointer to a non-array object created by a previous + + new-expression + + , or a pointer to a subobject (1.8)ย representing a base class of such an object (Clause 10). If not, the behavior is undefined. In the secondย alternative ( + + delete array + + ), the value of the operand of + + delete + + may be a null pointer value or a pointerย value that resulted from a previous array + + new-expression + + .ย If not, the behavior is undefined. +

    -

    Deallocating a pointer that is not allocated dynamically (including non-dynamic pointers returned from calls to placement new()) is undefined behavior because the pointer value was not obtained by an allocation function. Deallocating a pointer that has already been passed to a deallocation function is undefined behavior because the pointer value no longer points to memory that has been dynamically allocated.

    -

    When an operator such as new is called, it results in a call to an overloadable operator of the same name, such as operator new(). These overloadable functions can be called directly but carry the same restrictions as their operator counterparts. That is, calling operator delete() and passing a pointer parameter has the same constraints as calling the delete operator on that pointer. Further, the overloads are subject to scope resolution, so it is possible (but not permissible) to call a class-specific operator to allocate an object but a global operator to deallocate the object.

    -

    See MEM53-CPP. Explicitly construct and destruct objects when manually managing object lifetime for information on lifetime management of objects when using memory management functions other than the new and delete operators.

    +

    + Deallocating a pointer that is not allocated dynamically (including non-dynamic pointers returned from calls to placement + + new() + + ) is undefined behavior because the pointer value was not obtained by an allocation function. Deallocating a pointer that has already + been passed to a deallocation function is undefined behavior because the pointer value no longer points to memory that has been dynamically allocated. +

    +

    + When an operator such as + + new + + is called, it results in a call to an overloadable operator of the same name, such as + + operator new() + + . These overloadable functions can be called directly but carry the same restrictions as their operator counterparts. That is, calling + + operator delete() + + and passing a pointer parameter has the same constraints as calling the + + delete + + operator on that pointer. Further, the overloads are subject to scope resolution, so it is possible (but not permissible) to call a class-specific operator to allocate an object but a global operator to deallocate the object. +

    +

    + See + + MEM53-CPP. Explicitly construct and destruct objects when manually managing object lifetime + + for information on lifetime management of objects when using memory management functions other than the + + new + + and + + delete + + operators. +

    -
    -

    In this noncompliant code example, the local variable space is passed as the expression to the placement new operator. The resulting pointer of that call is then passed to ::operator delete(), resulting in undefined behavior due to ::operator delete() attempting to free memory that was not returned by ::operator new().

    - #include <iostream> - +
    +

    + In this noncompliant code example, the local variable + + space + + is passed as the expression to the placement + + new + + operator. The resulting pointer of that call is then passed to + + ::operator delete() + + , resulting in + + undefined behavior + + due to + + ::operator delete() + + attempting to free memory that was not returned by + + ::operator new() + + . +

    + + #include <iostream> +ย  struct S { S() { std::cout << "S::S()" << std::endl; } ~S() { std::cout << "S::~S()" << std::endl; } @@ -125,11 +325,23 @@ void f() { // ... delete s1; -} +} +
    -
    -

    This compliant solution removes the call to ::operator delete(), instead explicitly calling s1's destructor. This is one of the few times when explicitly invoking a destructor is warranted.

    - #include <iostream> +
    +

    + This compliant solution removes the call to + + ::operator delete() + + , instead explicitly calling + + s1 + + 's destructor. This is one of the few times when explicitly invoking a destructor is warranted. +

    + + #include <iostream> struct S { S() { std::cout << "S::S()" << std::endl; } @@ -143,12 +355,44 @@ void f() { // ... s1->~S(); -} +} +
    -
    -

    In this noncompliant code example, two allocations are attempted within the same try block, and if either fails, the catch handler attempts to free resources that have been allocated. However, because the pointer variables have not been initialized to a known value, a failure to allocate memory for i1 may result in passing ::operator delete() a value (in i2) that was not previously returned by a call to ::operator new(), resulting in undefined behavior.

    - #include <new> - +
    +

    + In this noncompliant code example, two allocations are attempted within the same + + try + + block, and if either fails, the + + catch + + handler attempts to free resources that have been allocated. However, because the pointer variables have not been initialized to a known value, a failure to allocate memory for + + i1 + + may result in passing + + ::operator delete() + + a value (in + + i2 + + )ย that was not previously returned by a call to + + ::operator new() + + , resulting in + + undefined behavior + + . +

    + + #include <new> +ย  void f() { int *i1, *i2; try { @@ -158,12 +402,23 @@ void f() { delete i1; delete i2; } -} +} +
    -
    -

    This compliant solution initializes both pointer values to nullptr, which is a valid value to pass to ::operator delete().

    - #include <new> - +
    +

    + This compliant solution initializes both pointer values to + + nullptr + + , which is a valid value to pass to + + ::operator delete(). + +

    + + #include <new> +ย  void f() { int *i1 = nullptr, *i2 = nullptr; try { @@ -173,16 +428,66 @@ void f() { delete i1; delete i2; } -} +} +
    -

    Once a pointer is passed to the proper deallocation function, that pointer value is invalidated. Passing the pointer to a deallocation function a second time when the pointer value has not been returned by a subsequent call to an allocation function results in an attempt to free memory that has not been allocated dynamically. The underlying data structures that manage the heap can become corrupted in a way that can introduce security vulnerabilities into a program. These types of issues are called double-free vulnerabilities. In practice, double-free vulnerabilities can be exploited to execute arbitrary code.

    -

    In this noncompliant code example, the class C is given ownership of a P *, which is subsequently deleted by the class destructor. The C++ Standard, [class.copy], paragraph 7 [ISO/IEC 14882-2014], states the following:

    +

    + Once a pointer is passed to the proper deallocation function, that pointer value is invalidated. Passing the pointer to a deallocation function a second time when the pointer value has not been returned by a subsequent call to an allocation function results in an attempt to free memory that has not been allocated dynamically. The underlying data structures that manage the heap can become corrupted in a way that can introduce security + + vulnerabilities + + into a program. These types of issues are called + + double-free vulnerabilities + + . In practice, double-free vulnerabilities can be + + exploited + + to execute arbitrary code. +

    +

    + In this noncompliant code example, the class + + C + + is given ownership of a + + P * + + , which is subsequently deleted by the class destructor. The C++ Standard,ย [class.copy], paragraph 7 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

    +

    + If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the classย definition declares a move constructor or move assignment operator, the implicitly declared copy constructorย is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class hasย a user-declared copy assignment operator or a user-declared destructor. +

    -

    Despite the presence of a user-declared destructor, C will have an implicitly defaulted copy constructor defined for it, and this defaulted copy constructor will copy the pointer value stored in p, resulting in a double-free: the first free happens when g() exits and the second free happens when h() exits.

    - struct P {}; +

    + Despite the presence of a user-declared destructor, + + C + + will have an implicitly defaulted copy constructor defined for it, and this defaulted copy constructor will copy the pointer value stored in + + p + + , resulting in a double-free: the first free happens when + + g() + + exits and the second free happens when + + h() + + exits. +

    + + struct P {}; class C { P *p; @@ -202,11 +507,31 @@ void h() { P *p = new P; C c(p); g(c); -} +} +
    -

    In this compliant solution, the copy constructor and copy assignment operator for C are explicitly deleted. This deletion would result in an ill-formed program with the definition of g() from the preceding noncompliant code example due to use of the deleted copy constructor. Consequently, g() was modified to accept its parameter by reference, removing the double-free.

    - struct P {}; +

    + In this compliant solution, the copy constructor and copy assignment operator for + + C + + are explicitly deleted. This deletion would result in an + + ill-formed + + program with the definition of + + g() + + from the preceding noncompliant code example due to use of the deleted copy constructor. Consequently, + + g() + + was modified to accept its parameter by reference, removing the double-free. +

    + + struct P {}; class C { P *p; @@ -215,7 +540,7 @@ public: C(P *p) : p(p) {} C(const C&) = delete; ~C() { delete p; } - +ย  void operator=(const C&) = delete; void f() {} @@ -229,54 +554,148 @@ void h() { P *p = new P; C c(p); g(c); -} +} +
    -
    -

    In the following noncompliant code example, an array is allocated with array new[] but is deallocated with a scalar delete call instead of an array delete[] call, resulting in undefined behavior.

    - void f() { +
    +

    + In the following noncompliant code example, an array is allocated with array + + new[] + + but is deallocated with a scalar + + delete + + call instead of an array + + delete[] + + call, resulting in + + undefined behavior + + . +

    + + void f() { int *array = new int[10]; // ... delete array; -} +} +
    -
    +
    -
    - void f() { +
    + + void f() { int *array = new int[10]; // ... delete[] array; } - +
    -

    In this noncompliant code example, the call to malloc() is mixed with a call to delete.

    - #include <cstdlib> +

    + In this noncompliant code example, the call to + + malloc() + + is mixed with a call to + + delete + + . +

    + + #include <cstdlib> void f() { int *i = static_cast<int *>(std::malloc(sizeof(int))); // ... delete i; } - -

    This code does not violate MEM53-CPP. Explicitly construct and destruct objects when manually managing object lifetime because it complies with the MEM53-CPP-EX1 exception.

    +
    +

    + This code does not violate + + MEM53-CPP. Explicitly construct and destruct objects when manually managing object lifetime + + because it complies with the MEM53-CPP-EX1 exception. +

    -

    Some implementations of ::operator new() result in calling std::malloc(). On such implementations, the ::operator delete() function is required to call std::free() to deallocate the pointer, and the noncompliant code example would behave in a well-defined manner. However, this is an implementation detail and should not be relied onโ€”implementations are under no obligation to use underlying C memory management functions to implement C++ memory management operators.

    +

    + Some implementations of + + ::operator new() + + result in calling + + std::malloc() + + . On such implementations, the + + ::operator delete() + + function is required to call + + std::free() + + to deallocate the pointer, and the noncompliant code example would behave in a well-defined manner. However, this is an + + implementation + + detail and should not be relied onโ€”implementations are under no obligation to use underlying C memory management functions to implement C++ memory management operators. +

    -

    In this compliant solution, the pointer allocated by std::malloc() is deallocated by a call to std::free() instead of delete.

    - #include <cstdlib> +

    + In this compliant solution, the pointer allocated by + + std::malloc() + + is deallocated by a call to + + std::free() + + instead of + + delete. + +

    + + #include <cstdlib> void f() { int *i = static_cast<int *>(std::malloc(sizeof(int))); // ... std::free(i); -} +} +
    -

    In this noncompliant code example, std::free() is called to deallocate memory that was allocated by new. A common side effect of the undefined behavior caused by using the incorrect deallocation function is that destructors will not be called for the object being deallocated by std::free().

    - #include <cstdlib> - +

    + In this noncompliant code example, + + std::free() + + is called to deallocate memory that was allocated by + + new + + . A common side effect of the + + undefined behavior + + caused by using the incorrect deallocation function is that destructors will not be called for the object being deallocated by + + std::free(). + +

    + + #include <cstdlib> +ย  struct S { ~S(); }; @@ -285,12 +704,33 @@ void f() { S *s = new S(); // ... std::free(s); -} -

    Additionally, this code violates MEM53-CPP. Explicitly construct and destruct objects when manually managing object lifetime.

    +} +
    +

    + Additionally, this code violates + + MEM53-CPP. Explicitly construct and destruct objects when manually managing object lifetime + + . +

    -

    In this compliant solution, the pointer allocated by new is deallocated by calling delete instead of std::free().

    - struct S { +

    + In this compliant solution, the pointer allocated by + + new + + is deallocated by calling + + delete + + instead of + + std::free(). + +

    + + struct S { ~S(); }; @@ -298,13 +738,49 @@ void f() { S *s = new S(); // ... delete s; -} +} +
    -
    -

    In this noncompliant code example, the global new operator is overridden by a class-specific implementation of operator new(). When new is called, the class-specific override is selected, so S::operator new() is called. However, because the object is destroyed with a scoped ::delete operator, the global operator delete() function is called instead of the class-specific implementation S::operator delete(), resulting in undefined behavior.

    - #include <cstdlib> +
    +

    + In this noncompliant code example, the global + + new + + operator is overridden by a class-specific implementation of + + operator new() + + . When + + new + + is called, the class-specific override is selected, so + + S::operator new() + + is called. However, because the object is destroyed with a scoped + + ::delete + + operator, the global + + operator delete() + + function is called instead of the class-specific implementation + + S::operator delete() + + , resulting in + + undefined behavior + + . +

    + + #include <cstdlib> #include <new> - +ย  struct S { static void *operator new(std::size_t size) noexcept(true) { return std::malloc(size); @@ -318,11 +794,27 @@ struct S { void f() { S *s = new S; ::delete s; -} +} +
    -
    -

    In this compliant solution, the scoped ::delete call is replaced by a nonscoped delete call, resulting in S::operator delete() being called.

    - #include <cstdlib> +
    +

    + In this compliant solution, the scoped + + ::delete + + call is replaced by a nonscoped + + delete + + call, resulting in + + S::operator delete() + + being called. +

    + + #include <cstdlib> #include <new> struct S { @@ -338,51 +830,148 @@ struct S { void f() { S *s = new S; delete s; -} +} +
    -

    In this noncompliant code example, a std::unique_ptr is declared to hold a pointer to an object, but is direct-initialized with an array of objects. When the std::unique_ptr is destroyed, its default deleter calls delete instead of delete[], resulting in undefined behavior.

    - #include <memory> +

    + In this noncompliant code example, a + + std::unique_ptr + + is declared to hold a pointer to an object, but is direct-initialized with an array of objects. When the + + std::unique_ptr + + is destroyed, its default deleter calls + + delete + + instead of + + delete[] + + , resulting in undefined behavior. +

    + + #include <memory> struct S {}; void f() { std::unique_ptr<S> s{new S[10]}; -} +} +
    -

    In this compliant solution, the std::unique_ptr is declared to hold an array of objects instead of a pointer to an object. Additionally, std::make_unique() is used to initialize the smart pointer.

    - #include <memory> +

    + In this compliant solution, the + + std::unique_ptr + + is declared to hold an array of objects instead of a pointer to an object. Additionally, + + std::make_unique() + + is used to initialize the smart pointer. +

    + + #include <memory> struct S {}; void f() { std::unique_ptr<S[]> s = std::make_unique<S[]>(10); -} -

    Use of std::make_unique() instead of direct initialization will emit a diagnostic if the resulting std::unique_ptr is not of the correct type. Had it been used in the noncompliant code example, the result would have been an ill-formed program instead of undefined behavior. It is best to use std::make_unique() instead of manual initialization by other means.

    +} +
    +

    + Use of + + std::make_unique() + + instead of direct initialization will emit a diagnostic if the resulting + + std::unique_ptr + + is not of the correct type. Had it been used in the noncompliant code example, the result would have been an ill-formed program instead of undefined behavior. It is best to use + + std::make_unique() + + instead of manual initialization by other means. +

    -

    In this noncompliant code example, a std::shared_ptr is declared to hold a pointer to an object, but is direct-initialized with an array of objects. As with std::unique_ptr, when the std::shared_ptr is destroyed, its default deleter calls delete instead of delete[], resulting in undefined behavior.

    - #include <memory> +

    + In this noncompliant code example, a + + std::shared_ptr + + is declared to hold a pointer to an object, but is direct-initialized with an array of objects. As with + + std::unique_ptr + + ,ย when the + + std::shared_ptr + + is destroyed, its default deleter calls + + delete + + instead of + + delete[] + + , resulting in undefined behavior. +

    + + #include <memory> struct S {}; void f() { std::shared_ptr<S> s{new S[10]}; -} +} +
    -

    Unlike the compliant solution for std::unique_ptr, where std::make_unique() is called to create a unique pointer to an array, it is ill-formed to call std::make_shared() with an array type. Instead, this compliant solution manually specifies a custom deleter for the shared pointer type, ensuring that the underlying array is properly deleted.

    - #include <memory> +

    + Unlike the compliant solution for + + std::unique_ptr + + , where + + std::make_unique() + + is called to create a unique pointer to an array,ย it is ill-formed to call + + std::make_shared() + + with an array type. Instead, this compliant solution manually specifies a custom deleter for the shared pointer type, ensuring that the underlying array is properly deleted. +

    + + #include <memory> struct S {}; void f() { std::shared_ptr<S> s{new S[10], [](const S *ptr) { delete [] ptr; }}; -} +} +
    -

    Passing a pointer value to a deallocation function that was not previously obtained by the matching allocation function results in undefined behavior, which can lead to exploitable vulnerabilities.

    +

    + Passing a pointer value to a deallocation function that was not previously obtained by the matching allocation function results in + + undefined behavior + + , which can lead to exploitable + + vulnerabilities + + . +

    @@ -419,10 +1008,14 @@ void f() { Medium @@ -455,7 +1048,10 @@ void f() { 20.10 @@ -470,7 +1066,9 @@ void f() { 7.2.0 @@ -485,12 +1083,19 @@ void f() { 3.9 @@ -501,10 +1106,14 @@ void f() { @@ -537,17 +1148,43 @@ void f() { 2021.4 @@ -561,8 +1198,11 @@ void f() { @@ -634,8 +1282,18 @@ void f() { 4.4 @@ -647,22 +1305,50 @@ void f() { @@ -677,7 +1363,11 @@ void f() { 4.10 @@ -686,7 +1376,17 @@ void f() {
    - P18 + + P18 + - L1 + + L1 +
    - invalid_dynamic_memory_allocationdangling_pointer_use + + invalid_dynamic_memory_allocation + dangling_pointer_use + - CertC++-MEM51 + + CertC++-MEM51 + - clang-analyzer-cplusplus.NewDeleteLeaks - -Wmismatched-new-deleteclang-analyzer-unix.MismatchedDeallocator + + clang-analyzer-cplusplus.NewDeleteLeaks + + + -Wmismatched-new-delete + clang-analyzer-unix.MismatchedDeallocator + Checked by - clang-tidy + + clang-tidy + , but does not catch all violations of this rule
    - 6.2p0 + 6.1p0 - ALLOC.FNHALLOC.DFALLOC.TM + + ALLOC.FNH + ALLOC.DF + ALLOC.TM + Free non-heap variable @@ -522,7 +1131,9 @@ void f() { 2021.2 - C++2110, C++2111, C++2112, C++2113, C++2118, C++3337, C++3339, C++4262, C++4263, C++4264 + + C++2110, C++2111, C++2112, C++2113, C++2118, C++3337, C++3339, C++4262, C++4263, C++4264 + - CL.FFM.ASSIGN - CL.FFM.COPY - CL.FMM - CL.SHALLOW.ASSIGNCL.SHALLOW.COPY - FMM.MIGHT - FMM.MUST - FNH.MIGHT - FNH.MUST - FUM.GEN.MIGHT - FUM.GEN.MUST - UNINIT.CTOR.MIGHTUNINIT.CTOR.MUSTUNINIT.HEAP.MIGHTUNINIT.HEAP.MUST + + CL.FFM.ASSIGN + + + CL.FFM.COPY + + + CL.FMM + + + CL.SHALLOW.ASSIGN + CL.SHALLOW.COPY + + + FMM.MIGHT + + + FMM.MUST + + + FNH.MIGHT + + + FNH.MUST + + + FUM.GEN.MIGHT + + + FUM.GEN.MUST + + + UNINIT.CTOR.MIGHT + UNINIT.CTOR.MUST + UNINIT.HEAP.MIGHT + UNINIT.HEAP.MUST + - 232 S, 236 S, 239 S, 407 S, 469 S, 470 S, 483 S, 484 S, 485 S, 64 D, 112 D - + + 232 S, 236 S, 239 S, 407 S, 469 S, 470 S, 483 S, 484 S, 485 S, 64 D, 112 D + + + Partially implemented @@ -578,10 +1218,18 @@ void f() { 2021.2 - CERT_CPP-MEM51-a - CERT_CPP-MEM51-b - CERT_CPP-MEM51-c - CERT_CPP-MEM51-d + + CERT_CPP-MEM51-a + + + CERT_CPP-MEM51-b + + + CERT_CPP-MEM51-c + + + CERT_CPP-MEM51-d + Use the same form in corresponding calls to new/malloc and delete/free @@ -620,7 +1268,7 @@ void f() { Checks for: - Invalid deletion of pointernvalid deletion of pointer, invalid free of pointernvalid free of pointer, deallocation of previously deallocated pointereallocation of previously deallocated pointer. + Invalid deletion of pointer, invalid free of pointer, deallocation of previously deallocated pointer. Rule partially covered.
    - 2110, 2111, 2112, 2113, 2118, - 3337, 3339, 4262, 4263, 4264 + + 2110, 2111, 2112, 2113, 2118 + + , + + + + + 3337, 3339 + + , 4262, 4263, 4264 + - 7.17 + 7.16 - V515 + + V515 + + + , - V554 + + V554 + + + , - V611 + + V611 + + + , - V701 + + V701 + + + , - V748 + + V748 + + + , - V773 + + V773 + + + , - V1066 + + + V1066 + + - S1232 + + + S1232 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -759,9 +1459,13 @@ void f() { @@ -775,13 +1479,21 @@ void f() { @@ -809,9 +1521,13 @@ void f() { diff --git a/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors-standard.qhelp b/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors-standard.qhelp index 45090007a1..19f76d9fab 100644 --- a/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors-standard.qhelp +++ b/cpp/cert/src/rules/MEM52-CPP/DetectAndHandleMemoryAllocationErrors-standard.qhelp @@ -1,30 +1,141 @@
    -

    The default memory allocation operator, ::operator new(std::size_t), throws a std::bad_alloc exception if the allocation fails. Therefore, you need not check whether calling ::operator new(std::size_t) results in nullptr. The nonthrowing form, ::operator new(std::size_t, const std::nothrow_t &), does not throw an exception if the allocation fails but instead returns nullptr. The same behaviors apply for the operator new[] versions of both allocation functions. Additionally, the default allocator object (std::allocator) uses ::operator new(std::size_t) to perform allocations and should be treated similarly.

    - T *p1 = new T; // Throws std::bad_alloc if allocation fails +

    + The default memory allocation operator, + + ::operator new(std::size_t) + + , throws a + + std::bad_alloc + + exception if the allocation fails. Therefore, you need not check whether calling + + ::operator new(std::size_t) + + results in + nullptr + . The nonthrowing form, + + ::operator new(std::size_t, const std::nothrow_t &) + + , does not throw an exception if the allocation fails but instead returns + + nullptr + + . The same behaviors apply for the + + operator new[] + + versions of both allocation functions. Additionally, the default allocator object ( + + std::allocator + + ) uses + + ::operator new(std::size_t) + + to perform allocations and should be treated similarly. +

    + + T *p1 = new T; // Throws std::bad_alloc if allocation fails T *p2 = new (std::nothrow) T; // Returns nullptr if allocation fails T *p3 = new T[1]; // Throws std::bad_alloc if the allocation fails -T *p4 = new (std::nothrow) T[1]; // Returns nullptr if the allocation fails -

    Furthermore, operator new[] can throw an error of type std::bad_array_new_length, a subclass of std::bad_alloc, if the size argument passed to new is negative or excessively large.

    -

    When using the nonthrowing form, it is imperative to check that the return value is not nullptr before accessing the resulting pointer. When using either form, be sure to comply with ERR50-CPP. Do not abruptly terminate the program.

    +T *p4 = new (std::nothrow) T[1]; // Returns nullptr if the allocation fails +
    +

    + Furthermore, + + operator new[] + + can throw an error of type + + std::bad_array_new_length + + , a subclass of + + std::bad_alloc + + , if the + + size + + argument passed to + + new + + is negative or excessively large. +

    +

    + When using the nonthrowing form, it is imperative to check that the return value is not + + nullptr + + before accessing the resulting pointer. When using either form, be sure to comply with + + ERR50-CPP. Do not abruptly terminate the program + + . +

    -

    In this noncompliant code example, an array of int is created using ::operator new[](std::size_t) and the results of the allocation are not checked. The function is marked as noexcept, so the caller assumes this function does not throw any exceptions. Because ::operator new[](std::size_t) can throw an exception if the allocation fails, it could lead to abnormal termination of the program.

    - #include <cstring> - +

    + In this noncompliant code example, an array of + + int + + is created using + + ::operator new[](std::size_t) + + and the results of the allocation are not checked. The function is marked as + + noexcept + + , so the caller assumes this function does not throw any exceptions. Because + + ::operator new[](std::size_t) + + can throw an exception if the allocation fails, it could lead to + + abnormal termination + + of the program. +

    + + #include <cstring> +ย  void f(const int *array, std::size_t size) noexcept { int *copy = new int[size]; std::memcpy(copy, array, size * sizeof(*copy)); // ... delete [] copy; } - +
    -

    When using std::nothrow, the new operator returns either a null pointer or a pointer to the allocated space. Always test the returned pointer to ensure it is not nullptr before referencing the pointer. This compliant solution handles the error condition appropriately when the returned pointer is nullptr.

    - #include <cstring> +

    + When using + + std::nothrow + + , the + + new + + operator returns either a null pointer or a pointer to the allocated space. Always test the returned pointer to ensure it is not + + nullptr + + before referencing the pointer. This compliant solution handles the error condition appropriately when the returned pointer is + + nullptr. + +

    + + #include <cstring> #include <new> void f(const int *array, std::size_t size) noexcept { @@ -36,11 +147,27 @@ void f(const int *array, std::size_t size) noexcept { std::memcpy(copy, array, size * sizeof(*copy)); // ... delete [] copy; -} +} +
    -

    Alternatively, you can use ::operator new[] without std::nothrow and instead catch a std::bad_alloc exception if sufficient memory cannot be allocated.

    - #include <cstring> +

    + Alternatively, you can use + + ::operator new[] + + without + + std::nothrow + + and instead catch a + + std::bad_alloc + + exception if sufficient memory cannot be allocated. +

    + + #include <cstring> #include <new> void f(const int *array, std::size_t size) noexcept { @@ -55,11 +182,19 @@ void f(const int *array, std::size_t size) noexcept { std::memcpy(copy, array, size * sizeof(*copy)); // ... delete [] copy; -} +} +
    -

    If the design of the function is such that the caller is expected to handle exceptional situations, it is permissible to mark the function explicitly as one that may throw, as in this compliant solution. Marking the function is not strictly required, as any function without a noexcept specifier is presumed to allow throwing.

    - #include <cstring> +

    + If the design of the function is such that the caller is expected to handle exceptional situations, it is permissible to mark the function explicitly as one that may throw, as in this compliant solution. Marking the function is not strictly required, as any function without a + + noexcept + + specifier is presumed to allow throwing. +

    + + #include <cstring> void f(const int *array, std::size_t size) noexcept(false) { int *copy = new int[size]; @@ -68,23 +203,100 @@ void f(const int *array, std::size_t size) noexcept(false) { std::memcpy(copy, array, size * sizeof(*copy)); // ... delete [] copy; -} +} +
    -

    In this noncompliant code example, two memory allocations are performed within the same expression. Because the memory allocations are passed as arguments to a function call, an exception thrown as a result of one of the calls to new could result in a memory leak.

    - struct A { /* ... */ }; -struct B { /* ... */ }; - +

    + In this noncompliant code example, two memory allocations are performed within the same expression. Because the memory allocations are passed as arguments to a function call, an exception thrown as a result of one of the calls to + + new + + could result in a memory leak. +

    + + struct A { /* ... */ }; +struct B { /* ... */ };ย  +ย  void g(A *, B *); void f() { g(new A, new B); -} -

    Consider the situation in which A is allocated and constructed first, and then B is allocated and throws an exception. Wrapping the call to g() in a try/catch block is insufficient because it would be impossible to free the memory allocated for A.

    -

    This noncompliant code example also violates EXP50-CPP. Do not depend on the order of evaluation for side effects, because the order in which the arguments to g() are evaluated is unspecified.

    +} +
    +

    + Consider the situation in which + + A + + is allocated and constructed first, and then + + B + + is allocated and throws an exception. Wrapping the call to + + g() + + in a + + try + + / + + catch + + block is insufficient because it would be impossible to free the memory allocated for + + A + + . +

    +

    + This noncompliant code example also violates + + EXP50-CPP. Do not depend on the order of evaluation for side effects + + , b + ecause the order in which the arguments to + + g() + + are evaluated is unspecified. +

    -

    In this compliant solution, a std::unique_ptr is used to manage the resources for the A and B objects with RAII. In the situation described by the noncompliant code example, B throwing an exception would still result in the destruction and deallocation of the A object when then std::unique_ptr<A> was destroyed.

    - #include <memory> +

    + In this compliant solution, a + + std::unique_ptr + + is used to manage the resources for the + + A + + and + + B + + objects with + + RAII + + . In the situation described by the noncompliant code example, + + B + + throwing an exception would still result in the destruction and deallocation of the + + A + + object when then + + std::unique_ptr<A> + + was destroyed. +

    + + #include <memory> struct A { /* ... */ }; struct B { /* ... */ }; @@ -92,11 +304,15 @@ struct B { /* ... */ }; void g(std::unique_ptr<A> a, std::unique_ptr<B> b); void f() { g(std::make_unique<A>(), std::make_unique<B>()); -} +} +
    -

    When possible, the more resilient compliant solution is to remove the memory allocation entirely and pass the objects by reference instead.

    - struct A { /* ... */ }; +

    + When possible, the more resilient compliant solution is to remove the memory allocation entirely and pass the objects by reference instead. +

    + + struct A { /* ... */ }; struct B { /* ... */ }; void g(A &a, B &b); @@ -104,11 +320,32 @@ void f() { A a; B b; g(a, b); -} +} +
    -

    Failing to detect allocation failures can lead to abnormal program termination and denial-of-service attacks.

    -

    If the vulnerable program references memory offset from the return value, an attacker can exploit the program to read or write arbitrary memory. This vulnerability has been used to execute arbitrary code [VU#159523].

    +

    + Failing to detect allocation failures can lead to + + abnormal program termination + + and + + denial-of-service attacks + + . +

    +

    + If the vulnerable program references memory offset from the return value, an attacker can exploit the program to read or write arbitrary memory. This + + vulnerability + + has been used to execute arbitrary code [ + + VU#159523 + + ]. +

    "Attacking - delete + + delete + and - delete [] + + delete [] + in C++"
    Rule 8.1, " - delete + + delete + should only be used with - new" + + new" + Rule 8.2, " - delete [] + + delete [] + should only be used with - new []" + + new []" +
    Item 16, "Use the Same Form in Corresponding Uses of - new + + new + and - delete + + delete + "
    @@ -145,10 +382,14 @@ void f() { Medium @@ -194,7 +435,9 @@ void f() { 7.5 @@ -225,18 +470,81 @@ void f() { 2021.4 @@ -250,7 +558,9 @@ void f() { @@ -328,10 +647,18 @@ void f() { @@ -340,8 +667,48 @@ void f() {
    - P18 + + P18 + - L1 + + L1 +
    - CHECKED_RETURN + + CHECKED_RETURN + Finds inconsistencies in how function call return values are handled @@ -210,7 +453,9 @@ void f() { 2021.2 - C++3225, C++3226, C++3227, C++3228, C++3229, C++4632 + + C++3225, C++3226, C++3227, C++3228, C++3229, C++4632 + - NPD.CHECK.CALL.MIGHT - NPD.CHECK.CALL.MUST - NPD.CHECK.MIGHT - NPD.CHECK.MUST - NPD.CONST.CALL - NPD.CONST.DEREF - NPD.FUNC.CALL.MIGHT - NPD.FUNC.CALL.MUST - NPD.FUNC.MIGHT - NPD.FUNC.MUST - NPD.GEN.CALL.MIGHTNPD.GEN.CALL.MUSTNPD.GEN.MIGHTNPD.GEN.MUST - RNPD.CALLRNPD.DEREF + + + NPD.CHECK.CALL.MIGHT + + + + + NPD.CHECK.CALL.MUST + + + + + NPD.CHECK.MIGHT + + + + + NPD.CHECK.MUST + + + + + NPD.CONST.CALL + + + + + NPD.CONST.DEREF + + + + + NPD.FUNC.CALL.MIGHT + + + + + NPD.FUNC.CALL.MUST + + + + + NPD.FUNC.MIGHT + + + + + NPD.FUNC.MUST + + + + + NPD.GEN.CALL.MIGHT + + + NPD.GEN.CALL.MUST + + + NPD.GEN.MIGHT + + + NPD.GEN. + + + MUST + + + + + RNPD.CALL + + + RNPD.DEREF + + - 45 D + + 45 D + Partially implemented @@ -266,8 +576,12 @@ void f() { 2021.2 - CERT_CPP-MEM52-a - CERT_CPP-MEM52-b + + CERT_CPP-MEM52-a + + + CERT_CPP-MEM52-b + Check the return value of new @@ -316,7 +630,12 @@ void f() { 4.4 - 3225, 3226, 3227, 3228, 3229, 4632 + + 3225, 3226, 3227, 3228, 3229, + + 4632 + + - 7.17 + 7.16 - V522, V668 + + + V522 + + , + + V668 + +
    -

    The vulnerability in Adobe Flash [VU#159523] arises because Flash neglects to check the return value from calloc(). Even though calloc() returns NULL, Flash does not attempt to read or write to the return value. Instead, it attempts to write to an offset from the return value. Dereferencing NULL usually results in a program crash, but dereferencing an offset from NULL allows an exploit to succeed without crashing the program.

    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + The + + vulnerability + + in Adobe Flash [ + + VU#159523 + + ] arises because Flash neglects to check the return value from + + calloc() + + . Even though + + calloc() + + returns + + NULL + + , Flash does not attempt to read or write to the return value. Instead, it attempts to write to an offset from the return value. Dereferencing + + NULL + + usually results in a program crash, but dereferencing an offset from + + NULL + + allows an + + exploit + + to succeed without crashing the program. +

    +

    + Search for vulnerabilities resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject-standard.qhelp b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject-standard.qhelp index 6acb82a64e..826a3e374c 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject-standard.qhelp +++ b/cpp/cert/src/rules/MEM53-CPP/MissingConstructorCallForManuallyManagedObject-standard.qhelp @@ -1,21 +1,176 @@
    -

    The creation of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for allocating sufficient memory to store the object, and the second stage is responsible for initializing the newly allocated chunk of memory, depending on the type of the object being created.

    -

    Similarly, the destruction of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for finalizing the object, depending on the type, and the second stage is responsible for deallocating the memory used by the object. The C++ Standard, [basic.life], paragraph 1 [ISO/IEC 14882-2014], states the following:

    +

    + The creation of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for allocating sufficient memory to store the object, and the second stage is responsible for initializing the newly allocated chunk of memory, depending on the type of the object being created. +

    +

    + Similarly, the destruction of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for finalizing the object, depending on the type, and the second stage is responsible for deallocating the memory used by the object. The C++ Standard,ย [basic.life], paragraph 1 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The lifetime of an object is a runtime property of the object. An object is said to have non-trivial initialization if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivial default constructor. [Note: initialization by a trivial copy/move constructor is non-trivial initialization. โ€” end note] The lifetime of an object of type T begins when:

    -

    โ€” storage with the proper alignment and size for type T is obtained, andโ€” if the object has non-trivial initialization, its initialization is complete.

    -

    The lifetime of an object of type T ends when:

    -

    โ€” if T is a class type with a non-trivial destructor, the destructor call starts, orโ€” the storage which the object occupies is reused or released.

    +

    + The + + lifetime + + of an object is a runtime property of the object. An object is said to have non-trivial initializationย if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivialย default constructor. [ + + Note: + + initialization by a trivial copy/move constructor is non-trivial initialization. โ€” + + end note + + ] The lifetime of an object of type + + T + + begins when: +

    +

    + โ€” storage with the proper alignment and size for type + + T + + is obtained, and + โ€” if the object has non-trivial initialization, its initialization is complete. +

    +

    + The lifetime of an object of type + + T + + ends when: +

    +

    + โ€” if + + T + + is a class type with a non-trivial destructor, the destructor call starts, or + โ€” the storage which the object occupies is reused or released. +

    -

    For a dynamically allocated object, these two stages are typically handled automatically by using the new and delete operators. The expression new T for a type T results in a call to operator new() to allocate sufficient memory for T. If memory is successfully allocated, the default constructor for T is called. The result of the expression is a pointer P to the object of type T. When that pointer is passed in the expression delete P, it results in a call to the destructor for T. After the destructor completes, a call is made to operator delete() to deallocate the memory.

    -

    When a program creates a dynamically allocated object by means other than the new operator, it is said to be manually managing the lifetime of that object. This situation arises when using other allocation schemes to obtain storage for the dynamically allocated object, such as using an allocator object or malloc(). For example, a custom container class may allocate a slab of memory in a reserve() function in which subsequent objects will be stored. See MEM51-CPP. Properly deallocate dynamically allocated resources for further information on dynamic memory management.

    -

    When manually managing the lifetime of an object, the constructor must be called to initiate the lifetime of the object. Similarly, the destructor must be called to terminate the lifetime of the object. Use of an object outside of its lifetime is undefined behavior. An object can be constructed either by calling the constructor explicitly using the placement new operator or by calling the construct() function of an allocator object. An object can be destroyed either by calling the destructor explicitly or by calling the destroy() function of an allocator object.

    +

    + For a dynamically allocated object, these two stages are typically handled automatically by using the + + new + + and + + delete + + operators. The expression + + new T + + for a type + + T + + results in a call to + + operator new() + + to allocate sufficient memory for + + T + + . If memory is successfully allocated, the default constructor for + + T + + is called. The result of the expression is a pointer + + P + + to the object of type + + T + + . When that pointer is passed in the expression + + deleteย P + + , it results in a call to the destructor for + + T + + . After the destructor completes, a call is made to + + operator delete() + + to deallocate the memory. +

    +

    + When a program creates a dynamically allocated object by means other than the + + new + + operator, it is said to be + + manually managing + + the lifetime of that object. This situation arises when using other allocation schemes to obtain storage for the dynamically allocated object, such as using an + + allocator object + + or + + malloc() + + . For example, a custom container class may allocate a slab of memory in a + + reserve() + + function in which subsequent objects will be stored. See + + MEM51-CPP. Properly deallocate dynamically allocated resources + + for further information on dynamic memory management. +

    +

    + When manually managing the lifetime of an object, the constructor must be called to initiate the lifetime of the object. Similarly, the destructor must be called to terminate the lifetime of the object. Use of an object outside of its lifetime is + + undefined behavior + + . An object can be constructed either by calling the constructor explicitly using the placement + + new + + operator or by calling the + + construct() + + function of an allocator object. An object can be destroyed either by calling the destructor explicitly or by calling the + + destroy() + + function of an allocator object. +

    -

    In this noncompliant code example, a class with nontrivial initialization (due to the presence of a user-provided constructor) is created with a call to std::malloc(). However, the constructor for the object is never called, resulting in undefined behavior when the class is later accessed by calling s->f().

    - #include <cstdlib> +

    + In this noncompliant code example, a class with nontrivial initialization (due to the presence of a user-provided constructor) is created with a call to + + std::malloc() + + . However, the constructor for the object is never called, resulting in + + undefined behavior + + when the class is later accessed by calling + + s->f() + + . +

    + + #include <cstdlib> struct S { S(); @@ -25,15 +180,19 @@ struct S { void g() { S *s = static_cast<S *>(std::malloc(sizeof(S))); - +ย  s->f(); - +ย  std::free(s); -} +} +
    -

    In this compliant solution, the constructor and destructor are both explicitly called. Further, to reduce the possibility of the object being used outside of its lifetime, the underlying storage is a separate variable from the live object.

    - #include <cstdlib> +

    + In this compliant solution, the constructor and destructor are both explicitly called. Further, to reduce the possibility of the object being used outside of its lifetime, the underlying storage is a separate variable from the live object. +

    + + #include <cstdlib> #include <new> struct S { @@ -47,14 +206,34 @@ void g() { S *s = new (ptr) S; s->f(); - +ย  s->~S(); std::free(ptr); -} +} +
    -

    In this noncompliant code example, a custom container class uses an allocator object to obtain storage for arbitrary element types. While the copy_elements() function is presumed to call copy constructors for elements being moved into the newly allocated storage, this example fails to explicitly call the default constructor for any additional elements being reserved. If such an element is accessed through the operator[]() function, it results in undefined behavior, depending on the type T.

    - #include <memory> +

    + In this noncompliant code example, a custom container class uses an allocator object to obtain storage for arbitrary element types. While the + + copy_elements() + + function is presumed to call copy constructors for elements being moved into the newly allocated storage,ย this example fails to explicitly call the default constructor for any additional elements being reserved. If such an element is accessed through the + + operator[]() + + function, it results in + + undefined behavior + + , depending on the type + + T + + . +

    + + #include <memory> template <typename T, typename Alloc = std::allocator<T>> class Container { @@ -81,11 +260,18 @@ public: T &operator[](size_t idx) { return underlyingStorage[idx]; } const T &operator[](size_t idx) const { return underlyingStorage[idx]; } -}; +}; +
    -

    In this compliant solution, all elements are properly initialized by explicitly calling copy or default constructors for T.

    - #include <memory> +

    + In this compliant solution, all elements are properly initialized by explicitly calling copy or default constructors for + + T. + +

    + + #include <memory> template <typename T, typename Alloc = std::allocator<T>> class Container { @@ -115,13 +301,45 @@ public: T &operator[](size_t idx) { return underlyingStorage[idx]; } const T &operator[](size_t idx) const { return underlyingStorage[idx]; } -}; +}; +
    -

    MEM53-CPP-EX1: If the object is trivially constructable, it need not have its constructor explicitly called to initiate the object's lifetime. If the object is trivially destructible, it need not have its destructor explicitly called to terminate the object's lifetime. These properties can be tested by calling std::is_trivially_constructible() and std::is_trivially_destructible() from <type_traits>. For instance, integral types such as int and long long do not require an explicit constructor or destructor call.

    +

    + + MEM53-CPP-EX1: + + If the object is trivially constructable, it need not have its constructor explicitly called to initiate the object's lifetime. If the object is trivially destructible, it need not have its destructor explicitly called to terminate the object's lifetime. These properties can be tested by calling + + std::is_trivially_constructible() + + and + + std::is_trivially_destructible() + + from + + <type_traits> + + .ย For instance, integral types such as + + int + + and + + long long + + do not require an explicit constructor or destructor call. +

    -

    Failing to properly construct or destroy an object leaves its internal state inconsistent, which can result in undefined behavior and accidental information exposure.

    +

    + Failing to properly construct or destroy an object leaves its internal state inconsistent, which can result in + + undefined behavior + + and accidental information exposure. +

    @@ -158,10 +376,14 @@ public: Medium @@ -194,7 +416,9 @@ public: 2021.2 @@ -209,7 +433,9 @@ public: 2021.2 @@ -234,7 +468,17 @@ public:
    - P18 + + P18 + - L1 + + L1 +
    - C++4761, C++4762, C++4766, C++4767 + + C++4761, C++4762, C++4766, C++4767 + - CERT_CPP-MEM53-a + + CERT_CPP-MEM53-a + Do not invoke malloc/realloc for objects having constructors @@ -222,10 +448,18 @@ public: - 7.17 + 7.16 - V630, V749 + + + V630 + + , + + V749 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject-standard.qhelp b/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject-standard.qhelp index 6acb82a64e..826a3e374c 100644 --- a/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject-standard.qhelp +++ b/cpp/cert/src/rules/MEM53-CPP/MissingDestructorCallForManuallyManagedObject-standard.qhelp @@ -1,21 +1,176 @@
    -

    The creation of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for allocating sufficient memory to store the object, and the second stage is responsible for initializing the newly allocated chunk of memory, depending on the type of the object being created.

    -

    Similarly, the destruction of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for finalizing the object, depending on the type, and the second stage is responsible for deallocating the memory used by the object. The C++ Standard, [basic.life], paragraph 1 [ISO/IEC 14882-2014], states the following:

    +

    + The creation of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for allocating sufficient memory to store the object, and the second stage is responsible for initializing the newly allocated chunk of memory, depending on the type of the object being created. +

    +

    + Similarly, the destruction of dynamically allocated objects in C++ happens in two stages. The first stage is responsible for finalizing the object, depending on the type, and the second stage is responsible for deallocating the memory used by the object. The C++ Standard,ย [basic.life], paragraph 1 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    The lifetime of an object is a runtime property of the object. An object is said to have non-trivial initialization if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivial default constructor. [Note: initialization by a trivial copy/move constructor is non-trivial initialization. โ€” end note] The lifetime of an object of type T begins when:

    -

    โ€” storage with the proper alignment and size for type T is obtained, andโ€” if the object has non-trivial initialization, its initialization is complete.

    -

    The lifetime of an object of type T ends when:

    -

    โ€” if T is a class type with a non-trivial destructor, the destructor call starts, orโ€” the storage which the object occupies is reused or released.

    +

    + The + + lifetime + + of an object is a runtime property of the object. An object is said to have non-trivial initializationย if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivialย default constructor. [ + + Note: + + initialization by a trivial copy/move constructor is non-trivial initialization. โ€” + + end note + + ] The lifetime of an object of type + + T + + begins when: +

    +

    + โ€” storage with the proper alignment and size for type + + T + + is obtained, and + โ€” if the object has non-trivial initialization, its initialization is complete. +

    +

    + The lifetime of an object of type + + T + + ends when: +

    +

    + โ€” if + + T + + is a class type with a non-trivial destructor, the destructor call starts, or + โ€” the storage which the object occupies is reused or released. +

    -

    For a dynamically allocated object, these two stages are typically handled automatically by using the new and delete operators. The expression new T for a type T results in a call to operator new() to allocate sufficient memory for T. If memory is successfully allocated, the default constructor for T is called. The result of the expression is a pointer P to the object of type T. When that pointer is passed in the expression delete P, it results in a call to the destructor for T. After the destructor completes, a call is made to operator delete() to deallocate the memory.

    -

    When a program creates a dynamically allocated object by means other than the new operator, it is said to be manually managing the lifetime of that object. This situation arises when using other allocation schemes to obtain storage for the dynamically allocated object, such as using an allocator object or malloc(). For example, a custom container class may allocate a slab of memory in a reserve() function in which subsequent objects will be stored. See MEM51-CPP. Properly deallocate dynamically allocated resources for further information on dynamic memory management.

    -

    When manually managing the lifetime of an object, the constructor must be called to initiate the lifetime of the object. Similarly, the destructor must be called to terminate the lifetime of the object. Use of an object outside of its lifetime is undefined behavior. An object can be constructed either by calling the constructor explicitly using the placement new operator or by calling the construct() function of an allocator object. An object can be destroyed either by calling the destructor explicitly or by calling the destroy() function of an allocator object.

    +

    + For a dynamically allocated object, these two stages are typically handled automatically by using the + + new + + and + + delete + + operators. The expression + + new T + + for a type + + T + + results in a call to + + operator new() + + to allocate sufficient memory for + + T + + . If memory is successfully allocated, the default constructor for + + T + + is called. The result of the expression is a pointer + + P + + to the object of type + + T + + . When that pointer is passed in the expression + + deleteย P + + , it results in a call to the destructor for + + T + + . After the destructor completes, a call is made to + + operator delete() + + to deallocate the memory. +

    +

    + When a program creates a dynamically allocated object by means other than the + + new + + operator, it is said to be + + manually managing + + the lifetime of that object. This situation arises when using other allocation schemes to obtain storage for the dynamically allocated object, such as using an + + allocator object + + or + + malloc() + + . For example, a custom container class may allocate a slab of memory in a + + reserve() + + function in which subsequent objects will be stored. See + + MEM51-CPP. Properly deallocate dynamically allocated resources + + for further information on dynamic memory management. +

    +

    + When manually managing the lifetime of an object, the constructor must be called to initiate the lifetime of the object. Similarly, the destructor must be called to terminate the lifetime of the object. Use of an object outside of its lifetime is + + undefined behavior + + . An object can be constructed either by calling the constructor explicitly using the placement + + new + + operator or by calling the + + construct() + + function of an allocator object. An object can be destroyed either by calling the destructor explicitly or by calling the + + destroy() + + function of an allocator object. +

    -

    In this noncompliant code example, a class with nontrivial initialization (due to the presence of a user-provided constructor) is created with a call to std::malloc(). However, the constructor for the object is never called, resulting in undefined behavior when the class is later accessed by calling s->f().

    - #include <cstdlib> +

    + In this noncompliant code example, a class with nontrivial initialization (due to the presence of a user-provided constructor) is created with a call to + + std::malloc() + + . However, the constructor for the object is never called, resulting in + + undefined behavior + + when the class is later accessed by calling + + s->f() + + . +

    + + #include <cstdlib> struct S { S(); @@ -25,15 +180,19 @@ struct S { void g() { S *s = static_cast<S *>(std::malloc(sizeof(S))); - +ย  s->f(); - +ย  std::free(s); -} +} +
    -

    In this compliant solution, the constructor and destructor are both explicitly called. Further, to reduce the possibility of the object being used outside of its lifetime, the underlying storage is a separate variable from the live object.

    - #include <cstdlib> +

    + In this compliant solution, the constructor and destructor are both explicitly called. Further, to reduce the possibility of the object being used outside of its lifetime, the underlying storage is a separate variable from the live object. +

    + + #include <cstdlib> #include <new> struct S { @@ -47,14 +206,34 @@ void g() { S *s = new (ptr) S; s->f(); - +ย  s->~S(); std::free(ptr); -} +} +
    -

    In this noncompliant code example, a custom container class uses an allocator object to obtain storage for arbitrary element types. While the copy_elements() function is presumed to call copy constructors for elements being moved into the newly allocated storage, this example fails to explicitly call the default constructor for any additional elements being reserved. If such an element is accessed through the operator[]() function, it results in undefined behavior, depending on the type T.

    - #include <memory> +

    + In this noncompliant code example, a custom container class uses an allocator object to obtain storage for arbitrary element types. While the + + copy_elements() + + function is presumed to call copy constructors for elements being moved into the newly allocated storage,ย this example fails to explicitly call the default constructor for any additional elements being reserved. If such an element is accessed through the + + operator[]() + + function, it results in + + undefined behavior + + , depending on the type + + T + + . +

    + + #include <memory> template <typename T, typename Alloc = std::allocator<T>> class Container { @@ -81,11 +260,18 @@ public: T &operator[](size_t idx) { return underlyingStorage[idx]; } const T &operator[](size_t idx) const { return underlyingStorage[idx]; } -}; +}; +
    -

    In this compliant solution, all elements are properly initialized by explicitly calling copy or default constructors for T.

    - #include <memory> +

    + In this compliant solution, all elements are properly initialized by explicitly calling copy or default constructors for + + T. + +

    + + #include <memory> template <typename T, typename Alloc = std::allocator<T>> class Container { @@ -115,13 +301,45 @@ public: T &operator[](size_t idx) { return underlyingStorage[idx]; } const T &operator[](size_t idx) const { return underlyingStorage[idx]; } -}; +}; +
    -

    MEM53-CPP-EX1: If the object is trivially constructable, it need not have its constructor explicitly called to initiate the object's lifetime. If the object is trivially destructible, it need not have its destructor explicitly called to terminate the object's lifetime. These properties can be tested by calling std::is_trivially_constructible() and std::is_trivially_destructible() from <type_traits>. For instance, integral types such as int and long long do not require an explicit constructor or destructor call.

    +

    + + MEM53-CPP-EX1: + + If the object is trivially constructable, it need not have its constructor explicitly called to initiate the object's lifetime. If the object is trivially destructible, it need not have its destructor explicitly called to terminate the object's lifetime. These properties can be tested by calling + + std::is_trivially_constructible() + + and + + std::is_trivially_destructible() + + from + + <type_traits> + + .ย For instance, integral types such as + + int + + and + + long long + + do not require an explicit constructor or destructor call. +

    -

    Failing to properly construct or destroy an object leaves its internal state inconsistent, which can result in undefined behavior and accidental information exposure.

    +

    + Failing to properly construct or destroy an object leaves its internal state inconsistent, which can result in + + undefined behavior + + and accidental information exposure. +

    @@ -158,10 +376,14 @@ public: Medium @@ -194,7 +416,9 @@ public: 2021.2 @@ -209,7 +433,9 @@ public: 2021.2 @@ -234,7 +468,17 @@ public:
    - P18 + + P18 + - L1 + + L1 +
    - C++4761, C++4762, C++4766, C++4767 + + C++4761, C++4762, C++4766, C++4767 + - CERT_CPP-MEM53-a + + CERT_CPP-MEM53-a + Do not invoke malloc/realloc for objects having constructors @@ -222,10 +448,18 @@ public: - 7.17 + 7.16 - V630, V749 + + + V630 + + , + + V749 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert-standard.qhelp b/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert-standard.qhelp index 68b77fb174..9b78a32e1d 100644 --- a/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM54-CPP/PlacementNewInsufficientStorageCert-standard.qhelp @@ -1,31 +1,160 @@
    -

    When invoked by a new expression for a given type, the default global non-placement forms of operator new attempt to allocate sufficient storage for an object of the type and, if successful, return a pointer with alignment suitable for any object with a fundamental alignment requirement. However, the default placement new operator simply returns the given pointer back to the caller without guaranteeing that there is sufficient space in which to construct the object or ensuring that the pointer meets the proper alignment requirements. The C++ Standard, [expr.new], paragraph 16 [ISO/IEC 14882-2014], nonnormatively states the following:

    +

    + When invoked by a + + new + + expression for a given type, the default global non-placement forms of + + operator new + + attempt to allocate sufficient storage for an object of the type and, if successful, return a pointer with alignment suitable for any object with a fundamental alignment requirement. However, the default placement + + new + + operator simply returns the given pointer back to the caller without guaranteeing that there is sufficient space in which to construct the object or ensuring that the pointer meets the proper alignment requirements. The C++ Standard,ย [expr.new], paragraph 16 [ + + ISO/IEC 14882-2014 + + ], nonnormatively states the following: +

    -

    [Note: when the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved. The block of storage is assumed to be appropriately aligned and of the requested size. The address of the created object will not necessarily be the same as that of the block if the object is an array. โ€”end note]

    +

    + [Note: when the allocation function returns a value other than null, it must be a pointer to a block of storageย in which space for the object has been reserved. The block of storage is assumed to be appropriately alignedย and of the requested size. The address of the created object will not necessarily be the same as that of theย block if the object is an array. โ€”end note] +

    -

    (This note is a reminder of the general requirements specified by the C++ Standard, [basic.stc.dynamic.allocation], paragraph 1, which apply to placement new operators by virtue of [basic.stc.dynamic], paragraph 3.)

    -

    In addition, the standard provides the following example later in the same section:

    +

    + (This note is a reminder of the general requirements specified by the C++ Standard,ย [basic.stc.dynamic.allocation], paragraph 1, which apply to placement + + new + + operators by virtue ofย [basic.stc.dynamic], paragraph 3.) +

    +

    + In addition, the standard provides the following example later in the same section: +

    -

    new(2, f) T[5] results in a call of operator new[](sizeof(T) * 5 + y, 2, f).

    -

    Here, ... and y are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[]. This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions. The amount of overhead may vary from one invocation of new to another.

    +

    + + new(2, f) T[5] + + results in a call + + of operator new[](sizeof(T) * 5 + y, 2, f). + +

    +

    + Here, + + ... + + and + + y + + are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by + + operator new[] + + . This overhead may be applied in all array + + new-expressions + + , including those referencing the library function + + operator new[](std::size_t, void*) + + and other placement allocation functions. The amount of overhead may vary from one invocation of new to another. +

    -

    Do not pass a pointer that is not suitably aligned for the object being constructed to placement new. Doing so results in an object being constructed at a misaligned location, which results in undefined behavior. Do not pass a pointer that has insufficient storage capacity for the object being constructed, including the overhead required for arrays. Doing so may result in initialization of memory outside of the bounds of the object being constructed, which results in undefined behavior.

    -

    Finally, do not use placement new[] on any platform that does not specify a limit for the overhead it requires.

    +

    + Do not pass a pointer that is not suitably aligned for the object being constructed to placement + + new + + . Doing so results in an object being constructed at a misaligned location, which results in + + undefined behavior + + . Do not pass a pointer that has insufficient storage capacity for the object being constructed, including the overhead required for arrays. Doing so may result in initialization of memory outside of the bounds of the object being constructed, which results in undefined behavior. +

    +

    + Finally, do not use placement + + new[] + + on any platform that does not specify a limit for the overhead it requires. +

    -

    In this noncompliant code example, a pointer to a short is passed to placement new, which is attempting to initialize a long. On architectures where sizeof(short) < sizeof(long), this results in undefined behavior. This example, and subsequent ones, all assume the pointer returned by placement new will not be used after the lifetime of its underlying storage has ended. For instance, the pointer will not be stored in a static global variable and dereferenced after the call to f() has ended. This assumption is in conformance with MEM50-CPP. Do not access freed memory.

    - #include <new> - +

    + In this noncompliant code example, a pointer to a + + short + + is passed to placement + + new + + , which is attempting to initialize a + + long + + . On architectures where + + sizeof(short) < sizeof(long) + + , this results in + + undefined behavior + + . This example, and subsequent ones, all assume the pointer returned by placement + + new + + will not be used after the lifetime of its underlying storage has ended. For instance, the pointer will not be stored in a + + static + + global variable and dereferenced after the call to + + f() + + has ended. This assumption is in conformance with + + MEM50-CPP. Do not access freed memory + + . +

    + + #include <new> +ย  void f() { short s; long *lp = ::new (&s) long; -} +} +
    -

    This noncompliant code example ensures that the long is constructed into a buffer of sufficient size. However, it does not ensure that the alignment requirements are met for the pointer passed into placement new. To make this example clearer, an additional local variable c has also been declared.

    - #include <new> +

    + This noncompliant code example ensures that the + + long + + is constructed into a buffer of sufficient size. However, it does not ensure that the alignment requirements are met for the pointer passed into placement + + new + + . To make this example clearer, an additional local variable + + c + + has also been declared. +

    + + #include <new> void f() { char c; // Used elsewhere in the function @@ -33,35 +162,62 @@ void f() { long *lp = ::new (buffer) long; // ... -} +} +
    -

    In this compliant solution, the alignas declaration specifier is used to ensure the buffer is appropriately aligned for a long.

    - #include <new> - +

    + In this compliant solution, the + + alignas + + declaration specifier is used to ensure the buffer is appropriately aligned for a + + long. + +

    + + #include <new> +ย  void f() { char c; // Used elsewhere in the function alignas(long) unsigned char buffer[sizeof(long)]; long *lp = ::new (buffer) long; - +ย  // ... -} +} +
    -

    This compliant solution ensures that the long is constructed into a buffer of sufficient size and with suitable alignment.

    - #include <new> - +

    + This compliant solution ensures that the + + long + + is constructed into a buffer of sufficient size and with suitable alignment. +

    + + #include <new> +ย  void f() { char c; // Used elsewhere in the function std::aligned_storage<sizeof(long), alignof(long)>::type buffer; long *lp = ::new (&buffer) long; - +ย  // ... -} +} +
    -

    This noncompliant code example attempts to allocate sufficient storage of the appropriate alignment for the array of objects of S. However, it fails to account for the overhead an implementation may add to the amount of storage for array objects. The overhead (commonly referred to as a cookie) is necessary to store the number of elements in the array so that the array delete expression or the exception unwinding mechanism can invoke the type's destructor on each successfully constructed element of the array. While some implementations are able to avoid allocating space for the cookie in some situations, assuming they do in all cases is unsafe.

    - #include <new> +

    + This noncompliant code example attempts to allocate sufficient storage of the appropriate alignment for the array of objects of + + S + + .ย  However, it fails to account for the overhead an implementation may add to the amount of storage for array objects.ย  The overhead (commonly referred to as a cookie) is necessary to store the number of elements in the array so that the array delete expression or the exception unwinding mechanism can invoke the type's destructor on each successfully constructed element of the array.ย  While some implementations are able to avoid allocating space for the cookie in some situations, assuming they do in all cases is unsafe. +

    + + #include <new> struct S { S (); @@ -78,11 +234,31 @@ void f() { for (size_t i = 0; i != n; ++i) { sp[i].~S(); } -} +} +
    -

    The amount of overhead required by array new expressions is unspecified but ideally would be documented by quality implementations. The following compliant solution is specifically for the Clang and GNU GCC compilers, which guarantee that the overhead for dynamic array allocations is a single value of type size_t. (Note that this value is often treated as a "-1th" element in the array, so the actual space used may be larger.) To verify that the assumption is, in fact, safe, the compliant solution also overloads the placement new[] operator to accept the buffer size as a third argument and verifies that it is not smaller than the total amount of storage required.

    - #include <cstddef> +

    + The amount of overhead required by array new expressions is unspecified but ideally would be documented by quality implementations. The following compliant solution is specifically for the + + Clang + + and GNU + + GCC + + compilers, which guarantee that the overhead for dynamic array allocations is a single value of type + + size_t + + . (Note that this value is often treated as a "-1th" element in the array, so the actual space used may be larger.) To verify that the assumption is, in fact, safe, the compliant solution also overloads the placement + + new[] + + operator to accept the buffer size as a third argument and verifies that it is not smaller than the total amount of storage required. +

    + + #include <cstddef> #include <new> #if defined(__clang__) || defined(__GNUG__) @@ -114,11 +290,28 @@ void f() { for (size_t i = 0; i != n; ++i) { sp[i].~S(); } -} -

    Porting this compliant solution to other implementations requires adding similar conditional definitions of the overhead constant, depending on the constraints of the platform.

    +} +
    +

    + Porting this compliant solution to other implementations requires adding similar conditional definitions of the overhead constant, depending on the constraints of the platform. +

    -

    Passing improperly aligned pointers or pointers to insufficient storage to placement new expressions can result in undefined behavior, including buffer overflow and abnormal termination.

    +

    + Passing improperly aligned pointers or pointers to insufficient storage to placement + + new + + expressions can result in + + undefined behavior + + , including buffer overflow and + + abnormal termination + + . +

    @@ -155,10 +348,14 @@ void f() { Medium @@ -191,7 +388,9 @@ void f() { 7.2.0 @@ -206,7 +405,9 @@ void f() { 2021.2 @@ -220,7 +421,9 @@ void f() { @@ -281,7 +492,17 @@ void f() {
    - P18 + + P18 + - L1 + + L1 +
    - CertC++-MEM54 + + CertC++-MEM54 + - C++3119, C++3128 + + C++3119, C++3128 + - 597 S + + 597 S + Enhanced Enforcement @@ -236,8 +439,12 @@ void f() { 2021.2 - CERT_CPP-MEM54-a - CERT_CPP-MEM54-b + + CERT_CPP-MEM54-a + + + CERT_CPP-MEM54-b + Do not pass a pointer that has insufficient storage capacity or that is not suitably aligned for the object being constructed to placement 'new' @@ -269,10 +476,14 @@ void f() { - 7.17 + 7.16 - V752 + + + V752 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert-standard.qhelp b/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert-standard.qhelp index 68b77fb174..9b78a32e1d 100644 --- a/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM54-CPP/PlacementNewNotProperlyAlignedCert-standard.qhelp @@ -1,31 +1,160 @@
    -

    When invoked by a new expression for a given type, the default global non-placement forms of operator new attempt to allocate sufficient storage for an object of the type and, if successful, return a pointer with alignment suitable for any object with a fundamental alignment requirement. However, the default placement new operator simply returns the given pointer back to the caller without guaranteeing that there is sufficient space in which to construct the object or ensuring that the pointer meets the proper alignment requirements. The C++ Standard, [expr.new], paragraph 16 [ISO/IEC 14882-2014], nonnormatively states the following:

    +

    + When invoked by a + + new + + expression for a given type, the default global non-placement forms of + + operator new + + attempt to allocate sufficient storage for an object of the type and, if successful, return a pointer with alignment suitable for any object with a fundamental alignment requirement. However, the default placement + + new + + operator simply returns the given pointer back to the caller without guaranteeing that there is sufficient space in which to construct the object or ensuring that the pointer meets the proper alignment requirements. The C++ Standard,ย [expr.new], paragraph 16 [ + + ISO/IEC 14882-2014 + + ], nonnormatively states the following: +

    -

    [Note: when the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved. The block of storage is assumed to be appropriately aligned and of the requested size. The address of the created object will not necessarily be the same as that of the block if the object is an array. โ€”end note]

    +

    + [Note: when the allocation function returns a value other than null, it must be a pointer to a block of storageย in which space for the object has been reserved. The block of storage is assumed to be appropriately alignedย and of the requested size. The address of the created object will not necessarily be the same as that of theย block if the object is an array. โ€”end note] +

    -

    (This note is a reminder of the general requirements specified by the C++ Standard, [basic.stc.dynamic.allocation], paragraph 1, which apply to placement new operators by virtue of [basic.stc.dynamic], paragraph 3.)

    -

    In addition, the standard provides the following example later in the same section:

    +

    + (This note is a reminder of the general requirements specified by the C++ Standard,ย [basic.stc.dynamic.allocation], paragraph 1, which apply to placement + + new + + operators by virtue ofย [basic.stc.dynamic], paragraph 3.) +

    +

    + In addition, the standard provides the following example later in the same section: +

    -

    new(2, f) T[5] results in a call of operator new[](sizeof(T) * 5 + y, 2, f).

    -

    Here, ... and y are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by operator new[]. This overhead may be applied in all array new-expressions, including those referencing the library function operator new[](std::size_t, void*) and other placement allocation functions. The amount of overhead may vary from one invocation of new to another.

    +

    + + new(2, f) T[5] + + results in a call + + of operator new[](sizeof(T) * 5 + y, 2, f). + +

    +

    + Here, + + ... + + and + + y + + are non-negative unspecified values representing array allocation overhead; the result of the new-expression will be offset by this amount from the value returned by + + operator new[] + + . This overhead may be applied in all array + + new-expressions + + , including those referencing the library function + + operator new[](std::size_t, void*) + + and other placement allocation functions. The amount of overhead may vary from one invocation of new to another. +

    -

    Do not pass a pointer that is not suitably aligned for the object being constructed to placement new. Doing so results in an object being constructed at a misaligned location, which results in undefined behavior. Do not pass a pointer that has insufficient storage capacity for the object being constructed, including the overhead required for arrays. Doing so may result in initialization of memory outside of the bounds of the object being constructed, which results in undefined behavior.

    -

    Finally, do not use placement new[] on any platform that does not specify a limit for the overhead it requires.

    +

    + Do not pass a pointer that is not suitably aligned for the object being constructed to placement + + new + + . Doing so results in an object being constructed at a misaligned location, which results in + + undefined behavior + + . Do not pass a pointer that has insufficient storage capacity for the object being constructed, including the overhead required for arrays. Doing so may result in initialization of memory outside of the bounds of the object being constructed, which results in undefined behavior. +

    +

    + Finally, do not use placement + + new[] + + on any platform that does not specify a limit for the overhead it requires. +

    -

    In this noncompliant code example, a pointer to a short is passed to placement new, which is attempting to initialize a long. On architectures where sizeof(short) < sizeof(long), this results in undefined behavior. This example, and subsequent ones, all assume the pointer returned by placement new will not be used after the lifetime of its underlying storage has ended. For instance, the pointer will not be stored in a static global variable and dereferenced after the call to f() has ended. This assumption is in conformance with MEM50-CPP. Do not access freed memory.

    - #include <new> - +

    + In this noncompliant code example, a pointer to a + + short + + is passed to placement + + new + + , which is attempting to initialize a + + long + + . On architectures where + + sizeof(short) < sizeof(long) + + , this results in + + undefined behavior + + . This example, and subsequent ones, all assume the pointer returned by placement + + new + + will not be used after the lifetime of its underlying storage has ended. For instance, the pointer will not be stored in a + + static + + global variable and dereferenced after the call to + + f() + + has ended. This assumption is in conformance with + + MEM50-CPP. Do not access freed memory + + . +

    + + #include <new> +ย  void f() { short s; long *lp = ::new (&s) long; -} +} +
    -

    This noncompliant code example ensures that the long is constructed into a buffer of sufficient size. However, it does not ensure that the alignment requirements are met for the pointer passed into placement new. To make this example clearer, an additional local variable c has also been declared.

    - #include <new> +

    + This noncompliant code example ensures that the + + long + + is constructed into a buffer of sufficient size. However, it does not ensure that the alignment requirements are met for the pointer passed into placement + + new + + . To make this example clearer, an additional local variable + + c + + has also been declared. +

    + + #include <new> void f() { char c; // Used elsewhere in the function @@ -33,35 +162,62 @@ void f() { long *lp = ::new (buffer) long; // ... -} +} +
    -

    In this compliant solution, the alignas declaration specifier is used to ensure the buffer is appropriately aligned for a long.

    - #include <new> - +

    + In this compliant solution, the + + alignas + + declaration specifier is used to ensure the buffer is appropriately aligned for a + + long. + +

    + + #include <new> +ย  void f() { char c; // Used elsewhere in the function alignas(long) unsigned char buffer[sizeof(long)]; long *lp = ::new (buffer) long; - +ย  // ... -} +} +
    -

    This compliant solution ensures that the long is constructed into a buffer of sufficient size and with suitable alignment.

    - #include <new> - +

    + This compliant solution ensures that the + + long + + is constructed into a buffer of sufficient size and with suitable alignment. +

    + + #include <new> +ย  void f() { char c; // Used elsewhere in the function std::aligned_storage<sizeof(long), alignof(long)>::type buffer; long *lp = ::new (&buffer) long; - +ย  // ... -} +} +
    -

    This noncompliant code example attempts to allocate sufficient storage of the appropriate alignment for the array of objects of S. However, it fails to account for the overhead an implementation may add to the amount of storage for array objects. The overhead (commonly referred to as a cookie) is necessary to store the number of elements in the array so that the array delete expression or the exception unwinding mechanism can invoke the type's destructor on each successfully constructed element of the array. While some implementations are able to avoid allocating space for the cookie in some situations, assuming they do in all cases is unsafe.

    - #include <new> +

    + This noncompliant code example attempts to allocate sufficient storage of the appropriate alignment for the array of objects of + + S + + .ย  However, it fails to account for the overhead an implementation may add to the amount of storage for array objects.ย  The overhead (commonly referred to as a cookie) is necessary to store the number of elements in the array so that the array delete expression or the exception unwinding mechanism can invoke the type's destructor on each successfully constructed element of the array.ย  While some implementations are able to avoid allocating space for the cookie in some situations, assuming they do in all cases is unsafe. +

    + + #include <new> struct S { S (); @@ -78,11 +234,31 @@ void f() { for (size_t i = 0; i != n; ++i) { sp[i].~S(); } -} +} +
    -

    The amount of overhead required by array new expressions is unspecified but ideally would be documented by quality implementations. The following compliant solution is specifically for the Clang and GNU GCC compilers, which guarantee that the overhead for dynamic array allocations is a single value of type size_t. (Note that this value is often treated as a "-1th" element in the array, so the actual space used may be larger.) To verify that the assumption is, in fact, safe, the compliant solution also overloads the placement new[] operator to accept the buffer size as a third argument and verifies that it is not smaller than the total amount of storage required.

    - #include <cstddef> +

    + The amount of overhead required by array new expressions is unspecified but ideally would be documented by quality implementations. The following compliant solution is specifically for the + + Clang + + and GNU + + GCC + + compilers, which guarantee that the overhead for dynamic array allocations is a single value of type + + size_t + + . (Note that this value is often treated as a "-1th" element in the array, so the actual space used may be larger.) To verify that the assumption is, in fact, safe, the compliant solution also overloads the placement + + new[] + + operator to accept the buffer size as a third argument and verifies that it is not smaller than the total amount of storage required. +

    + + #include <cstddef> #include <new> #if defined(__clang__) || defined(__GNUG__) @@ -114,11 +290,28 @@ void f() { for (size_t i = 0; i != n; ++i) { sp[i].~S(); } -} -

    Porting this compliant solution to other implementations requires adding similar conditional definitions of the overhead constant, depending on the constraints of the platform.

    +} +
    +

    + Porting this compliant solution to other implementations requires adding similar conditional definitions of the overhead constant, depending on the constraints of the platform. +

    -

    Passing improperly aligned pointers or pointers to insufficient storage to placement new expressions can result in undefined behavior, including buffer overflow and abnormal termination.

    +

    + Passing improperly aligned pointers or pointers to insufficient storage to placement + + new + + expressions can result in + + undefined behavior + + , including buffer overflow and + + abnormal termination + + . +

    @@ -155,10 +348,14 @@ void f() { Medium @@ -191,7 +388,9 @@ void f() { 7.2.0 @@ -206,7 +405,9 @@ void f() { 2021.2 @@ -220,7 +421,9 @@ void f() { @@ -281,7 +492,17 @@ void f() {
    - P18 + + P18 + - L1 + + L1 +
    - CertC++-MEM54 + + CertC++-MEM54 + - C++3119, C++3128 + + C++3119, C++3128 + - 597 S + + 597 S + Enhanced Enforcement @@ -236,8 +439,12 @@ void f() { 2021.2 - CERT_CPP-MEM54-a - CERT_CPP-MEM54-b + + CERT_CPP-MEM54-a + + + CERT_CPP-MEM54-b + Do not pass a pointer that has insufficient storage capacity or that is not suitably aligned for the object being constructed to placement 'new' @@ -269,10 +476,14 @@ void f() { - 7.17 + 7.16 - V752 + + + V752 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert-standard.qhelp b/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert-standard.qhelp index 005f1bb236..e89f641058 100644 --- a/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM55-CPP/OperatorDeleteMissingPartnerCert-standard.qhelp @@ -1,32 +1,92 @@
    -

    Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standard [ISO/IEC 14882-2014]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement. However, the C++ Standard, [res.on.functions], paragraph 1, states the following:

    +

    + Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standardย [ + + ISO/IEC 14882-2014 + + ]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement.ย However, the C++ Standard,ย [res.on.functions], paragraph 1, states the following: +

    -

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    +

    + In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. +

    -

    Paragraph 2 further, in part, states the following:

    +

    + Paragraph 2 further, in part, states the following: +

    -

    In particular, the effects are undefined in the following cases:โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable Required behavior: paragraph.

    +

    + In particular, the effects are undefined in the following cases: + โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable + + Required behavior: + + paragraph. +

    -

    A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function.

    +

    + A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate + + Required behavior: + + clause of the replaced function. +

    -

    In this noncompliant code example, the global operator new(std::size_t) function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type std::bad_alloc. By returning a null pointer instead of throwing, functions relying on the required behavior of operator new(std::size_t) to throw on memory allocations may instead attempt to dereference a null pointer. See EXP34-C. Do not dereference null pointers for more information.

    - #include <new> +

    + In this noncompliant code example, the global + + operator new(std::size_t) + + function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type + + std::bad_alloc + + . By returning a null pointer instead of throwing, functions relying on the required behavior of + + operator new(std::size_t) + + to throw on memory allocations may instead attempt to dereference a null pointer. See + + EXP34-C. Do not dereference null pointers + + for more information. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr return alloc_mem(size); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere -

    The declarations of the replacement operator delete() functions indicate that this noncompliant code example still complies with DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope.

    +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    +

    + The declarations of the replacement + + operator delete() + + functions indicate that this noncompliant code example still complies with + + DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope + + . +

    -

    This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a std::bad_alloc exception when the allocation fails.

    - #include <new> +

    + This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a + + std::bad_alloc + + exception when the allocation fails. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr @@ -35,12 +95,27 @@ void *operator new(std::size_t size) { } throw std::bad_alloc(); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    -

    Failing to meet the stated requirements for a replaceable dynamic storage function leads to undefined behavior. The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [Jack 2007, van Sprundel 2006]. The indicated severity is for this more severe case.

    +

    + Failing to meet the stated requirements for a replaceable dynamic storage function leads to + + undefined behavior + + . The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [ + + Jack 2007 + + , + + van Sprundel 2006 + + ]. The indicated severity is for this more severe case. +

    @@ -77,10 +152,14 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -113,7 +192,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -128,8 +209,16 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -144,7 +233,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    - P18 + + P18 + - L1 + + L1 +
    - C++4736, C++4737, C++4738, C++4739 + + C++4736, C++4737, C++4738, C++4739 + - CERT.MEM.OVERRIDE.DELETE - CERT.MEM.OVERRIDE.NEW + + + CERT.MEM.OVERRIDE.DELETE + + + + + CERT.MEM.OVERRIDE.NEW + + - CERT_CPP-MEM55-a + + CERT_CPP-MEM55-a + The user defined 'new' operator should throw the 'std::bad_alloc' exception when the allocation fails @@ -172,7 +263,17 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert-standard.qhelp b/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert-standard.qhelp index 005f1bb236..e89f641058 100644 --- a/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingNoThrowOperatorNewDeleteCert-standard.qhelp @@ -1,32 +1,92 @@
    -

    Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standard [ISO/IEC 14882-2014]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement. However, the C++ Standard, [res.on.functions], paragraph 1, states the following:

    +

    + Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standardย [ + + ISO/IEC 14882-2014 + + ]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement.ย However, the C++ Standard,ย [res.on.functions], paragraph 1, states the following: +

    -

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    +

    + In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. +

    -

    Paragraph 2 further, in part, states the following:

    +

    + Paragraph 2 further, in part, states the following: +

    -

    In particular, the effects are undefined in the following cases:โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable Required behavior: paragraph.

    +

    + In particular, the effects are undefined in the following cases: + โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable + + Required behavior: + + paragraph. +

    -

    A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function.

    +

    + A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate + + Required behavior: + + clause of the replaced function. +

    -

    In this noncompliant code example, the global operator new(std::size_t) function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type std::bad_alloc. By returning a null pointer instead of throwing, functions relying on the required behavior of operator new(std::size_t) to throw on memory allocations may instead attempt to dereference a null pointer. See EXP34-C. Do not dereference null pointers for more information.

    - #include <new> +

    + In this noncompliant code example, the global + + operator new(std::size_t) + + function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type + + std::bad_alloc + + . By returning a null pointer instead of throwing, functions relying on the required behavior of + + operator new(std::size_t) + + to throw on memory allocations may instead attempt to dereference a null pointer. See + + EXP34-C. Do not dereference null pointers + + for more information. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr return alloc_mem(size); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere -

    The declarations of the replacement operator delete() functions indicate that this noncompliant code example still complies with DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope.

    +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    +

    + The declarations of the replacement + + operator delete() + + functions indicate that this noncompliant code example still complies with + + DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope + + . +

    -

    This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a std::bad_alloc exception when the allocation fails.

    - #include <new> +

    + This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a + + std::bad_alloc + + exception when the allocation fails. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr @@ -35,12 +95,27 @@ void *operator new(std::size_t size) { } throw std::bad_alloc(); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    -

    Failing to meet the stated requirements for a replaceable dynamic storage function leads to undefined behavior. The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [Jack 2007, van Sprundel 2006]. The indicated severity is for this more severe case.

    +

    + Failing to meet the stated requirements for a replaceable dynamic storage function leads to + + undefined behavior + + . The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [ + + Jack 2007 + + , + + van Sprundel 2006 + + ]. The indicated severity is for this more severe case. +

    @@ -77,10 +152,14 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -113,7 +192,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -128,8 +209,16 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -144,7 +233,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    - P18 + + P18 + - L1 + + L1 +
    - C++4736, C++4737, C++4738, C++4739 + + C++4736, C++4737, C++4738, C++4739 + - CERT.MEM.OVERRIDE.DELETE - CERT.MEM.OVERRIDE.NEW + + + CERT.MEM.OVERRIDE.DELETE + + + + + CERT.MEM.OVERRIDE.NEW + + - CERT_CPP-MEM55-a + + CERT_CPP-MEM55-a + The user defined 'new' operator should throw the 'std::bad_alloc' exception when the allocation fails @@ -172,7 +263,17 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert-standard.qhelp b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert-standard.qhelp index 005f1bb236..e89f641058 100644 --- a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert-standard.qhelp @@ -1,32 +1,92 @@
    -

    Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standard [ISO/IEC 14882-2014]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement. However, the C++ Standard, [res.on.functions], paragraph 1, states the following:

    +

    + Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standardย [ + + ISO/IEC 14882-2014 + + ]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement.ย However, the C++ Standard,ย [res.on.functions], paragraph 1, states the following: +

    -

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    +

    + In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. +

    -

    Paragraph 2 further, in part, states the following:

    +

    + Paragraph 2 further, in part, states the following: +

    -

    In particular, the effects are undefined in the following cases:โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable Required behavior: paragraph.

    +

    + In particular, the effects are undefined in the following cases: + โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable + + Required behavior: + + paragraph. +

    -

    A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function.

    +

    + A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate + + Required behavior: + + clause of the replaced function. +

    -

    In this noncompliant code example, the global operator new(std::size_t) function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type std::bad_alloc. By returning a null pointer instead of throwing, functions relying on the required behavior of operator new(std::size_t) to throw on memory allocations may instead attempt to dereference a null pointer. See EXP34-C. Do not dereference null pointers for more information.

    - #include <new> +

    + In this noncompliant code example, the global + + operator new(std::size_t) + + function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type + + std::bad_alloc + + . By returning a null pointer instead of throwing, functions relying on the required behavior of + + operator new(std::size_t) + + to throw on memory allocations may instead attempt to dereference a null pointer. See + + EXP34-C. Do not dereference null pointers + + for more information. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr return alloc_mem(size); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere -

    The declarations of the replacement operator delete() functions indicate that this noncompliant code example still complies with DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope.

    +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    +

    + The declarations of the replacement + + operator delete() + + functions indicate that this noncompliant code example still complies with + + DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope + + . +

    -

    This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a std::bad_alloc exception when the allocation fails.

    - #include <new> +

    + This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a + + std::bad_alloc + + exception when the allocation fails. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr @@ -35,12 +95,27 @@ void *operator new(std::size_t size) { } throw std::bad_alloc(); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    -

    Failing to meet the stated requirements for a replaceable dynamic storage function leads to undefined behavior. The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [Jack 2007, van Sprundel 2006]. The indicated severity is for this more severe case.

    +

    + Failing to meet the stated requirements for a replaceable dynamic storage function leads to + + undefined behavior + + . The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [ + + Jack 2007 + + , + + van Sprundel 2006 + + ]. The indicated severity is for this more severe case. +

    @@ -77,10 +152,14 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -113,7 +192,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -128,8 +209,16 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -144,7 +233,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    - P18 + + P18 + - L1 + + L1 +
    - C++4736, C++4737, C++4738, C++4739 + + C++4736, C++4737, C++4738, C++4739 + - CERT.MEM.OVERRIDE.DELETE - CERT.MEM.OVERRIDE.NEW + + + CERT.MEM.OVERRIDE.DELETE + + + + + CERT.MEM.OVERRIDE.NEW + + - CERT_CPP-MEM55-a + + CERT_CPP-MEM55-a + The user defined 'new' operator should throw the 'std::bad_alloc' exception when the allocation fails @@ -172,7 +263,17 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.md b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.md new file mode 100644 index 0000000000..535a49f06d --- /dev/null +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewReturnsNullCert.md @@ -0,0 +1,81 @@ +# MEM55-CPP: Replacement operator new returns null instead of throwing std:bad_alloc +This query implements the CERT-C++ rule MEM55-CPP: + +> Honor replacement dynamic storage management requirements + + +## Description +Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by \[replacement.functions\], paragraph 2, of the C++ Standardย \[ [ ISO/IEC 14882-2014 ](https://wiki.sei.cmu.edu//confluence/display/cplusplus/AA.+Bibliography#AA.Bibliography-ISO/IEC14882-2014) \]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement.ย However, the C++ Standard,ย \[res.on.functions\], paragraph 1, states the following: + +> In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. + +Paragraph 2 further, in part, states the following: + +> In particular, the effects are undefined in the following cases: โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable Required behavior: paragraph. + +A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function. + + +## Noncompliant Code Example +In this noncompliant code example, the global ` operator new(std::size_t) ` function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, \[new.delete.single\], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type ` std::bad_alloc ` . By returning a null pointer instead of throwing, functions relying on the required behavior of ` operator new(std::size_t) ` to throw on memory allocations may instead attempt to dereference a null pointer. See [ EXP34-C. Do not dereference null pointers ](https://wiki.sei.cmu.edu//confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers) for more information. + +```cpp + + #include + +void *operator new(std::size_t size) { + extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr + return alloc_mem(size); +} +ย  +void operator delete(void *ptr) noexcept; // Defined elsewhere +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere + +``` +The declarations of the replacement ` operator delete() ` functions indicate that this noncompliant code example still complies with [ DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope ](https://wiki.sei.cmu.edu//confluence/display/cplusplus/DCL54-CPP.+Overload+allocation+and+deallocation+functions+as+a+pair+in+the+same+scope) . + + +## Compliant Solution +This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a ` std::bad_alloc ` exception when the allocation fails. + +```cpp + + #include + +void *operator new(std::size_t size) { + extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr + if (void *ret = alloc_mem(size)) { + return ret; + } + throw std::bad_alloc(); +} +ย  +void operator delete(void *ptr) noexcept; // Defined elsewhere +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere + +``` + +## Risk Assessment +Failing to meet the stated requirements for a replaceable dynamic storage function leads to [ undefined behavior ](https://wiki.sei.cmu.edu//confluence/display/cplusplus/BB.+Definitions#BB.Definitions-undefinedbehavior) . The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code \[ [ Jack 2007 ](https://wiki.sei.cmu.edu//confluence/display/cplusplus/AA.+Bibliography#AA.Bibliography-Jack07) , [ van Sprundel 2006 ](https://wiki.sei.cmu.edu//confluence/display/cplusplus/AA.+Bibliography#AA.Bibliography-vanSprundel06) \]. The indicated severity is for this more severe case. + +
    Rule Severity Likelihood Remediation Cost Priority Level
    MEM55-CPP High Likely Medium P18 L1
    + +## Automated Detection +
    Tool Version Checker Description
    Helix QAC 2021.2 C++4736, C++4737, C++4738, C++4739
    Klocwork 2021.4 CERT.MEM.OVERRIDE.DELETE CERT.MEM.OVERRIDE.NEW
    Parasoft C/C++test 2021.2 CERT_CPP-MEM55-a The user defined 'new' operator should throw the 'std::bad_alloc' exception when the allocation fails
    Polyspace Bug Finder R2021b CERT C++: MEM55-CPP Checks for replacement allocation/deallocation functions that do not meet requirements of the Standard (rule fully covered)
    + +## Related Vulnerabilities +Search for [ vulnerabilities ](https://wiki.sei.cmu.edu//confluence/display/cplusplus/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [ CERT website ](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+MEM55-CPP) . + + +## Related Guidelines +
    SEI CERT C++ Coding Standard DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope OOP56-CPP. Honor replacement handler requirements
    SEI CERT C Coding Standard EXP34-C. Do not dereference null pointers
    + +## Bibliography +
    \[ ISO/IEC 14882-2014 \] Subclause 17.6.4.8, "Other Functions" Subclause 18.6.1, "Storage Allocation and Deallocation"
    \[ Jack 2007 \]
    \[ van Sprundel 2006 \]
    + +## Implementation notes +None + + +## References +* CERT-C++: [MEM55-CPP: Honor replacement dynamic storage management requirements](https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682) . diff --git a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert-standard.qhelp b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert-standard.qhelp index 005f1bb236..e89f641058 100644 --- a/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM55-CPP/ThrowingOperatorNewThrowsInvalidExceptionCert-standard.qhelp @@ -1,32 +1,92 @@
    -

    Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standard [ISO/IEC 14882-2014]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement. However, the C++ Standard, [res.on.functions], paragraph 1, states the following:

    +

    + Dynamic memory allocation and deallocation functions can be globally replaced by custom implementations, as specified by [replacement.functions], paragraph 2, of the C++ Standardย [ + + ISO/IEC 14882-2014 + + ]. For instance, a user may profile the dynamic memory usage of an application and decide that the default allocator is not optimal for their usage pattern, and a different allocation strategy may be a marked improvement.ย However, the C++ Standard,ย [res.on.functions], paragraph 1, states the following: +

    -

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    +

    + In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. +

    -

    Paragraph 2 further, in part, states the following:

    +

    + Paragraph 2 further, in part, states the following: +

    -

    In particular, the effects are undefined in the following cases:โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable Required behavior: paragraph.

    +

    + In particular, the effects are undefined in the following cases: + โ€” for replacement functions, if the installed replacement function does not implement the semantics of the applicable + + Required behavior: + + paragraph. +

    -

    A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function.

    +

    + A replacement for any of the dynamic memory allocation or deallocation functions must meet the semantic requirements specified by the appropriate + + Required behavior: + + clause of the replaced function. +

    -

    In this noncompliant code example, the global operator new(std::size_t) function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type std::bad_alloc. By returning a null pointer instead of throwing, functions relying on the required behavior of operator new(std::size_t) to throw on memory allocations may instead attempt to dereference a null pointer. See EXP34-C. Do not dereference null pointers for more information.

    - #include <new> +

    + In this noncompliant code example, the global + + operator new(std::size_t) + + function is replaced by a custom implementation. However, the custom implementation fails to honor the behavior required by the function it replaces, as per the C++ Standard, [new.delete.single], paragraph 3. Specifically, if the custom allocator fails to allocate the requested amount of memory, the replacement function returns a null pointer instead of throwing an exception of type + + std::bad_alloc + + . By returning a null pointer instead of throwing, functions relying on the required behavior of + + operator new(std::size_t) + + to throw on memory allocations may instead attempt to dereference a null pointer. See + + EXP34-C. Do not dereference null pointers + + for more information. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr return alloc_mem(size); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere -

    The declarations of the replacement operator delete() functions indicate that this noncompliant code example still complies with DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope.

    +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    +

    + The declarations of the replacement + + operator delete() + + functions indicate that this noncompliant code example still complies with + + DCL54-CPP. Overload allocation and deallocation functions as a pair in the same scope + + . +

    -

    This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a std::bad_alloc exception when the allocation fails.

    - #include <new> +

    + This compliant solution implements the required behavior for the replaced global allocator function by properly throwing a + + std::bad_alloc + + exception when the allocation fails. +

    + + #include <new> void *operator new(std::size_t size) { extern void *alloc_mem(std::size_t); // Implemented elsewhere; may return nullptr @@ -35,12 +95,27 @@ void *operator new(std::size_t size) { } throw std::bad_alloc(); } - +ย  void operator delete(void *ptr) noexcept; // Defined elsewhere -void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere +
    -

    Failing to meet the stated requirements for a replaceable dynamic storage function leads to undefined behavior. The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [Jack 2007, van Sprundel 2006]. The indicated severity is for this more severe case.

    +

    + Failing to meet the stated requirements for a replaceable dynamic storage function leads to + + undefined behavior + + . The severity of risk depends heavily on the caller of the allocation functions, but in some situations, dereferencing a null pointer can lead to the execution of arbitrary code [ + + Jack 2007 + + , + + van Sprundel 2006 + + ]. The indicated severity is for this more severe case. +

    @@ -77,10 +152,14 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -113,7 +192,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -128,8 +209,16 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere @@ -144,7 +233,9 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    - P18 + + P18 + - L1 + + L1 +
    - C++4736, C++4737, C++4738, C++4739 + + C++4736, C++4737, C++4738, C++4739 + - CERT.MEM.OVERRIDE.DELETE - CERT.MEM.OVERRIDE.NEW + + + CERT.MEM.OVERRIDE.DELETE + + + + + CERT.MEM.OVERRIDE.NEW + + - CERT_CPP-MEM55-a + + CERT_CPP-MEM55-a + The user defined 'new' operator should throw the 'std::bad_alloc' exception when the allocation fails @@ -172,7 +263,17 @@ void operator delete(void *ptr, std::size_t) noexcept; // Defined elsewhere
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert-standard.qhelp b/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert-standard.qhelp index fd39239138..391ce4228f 100644 --- a/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert-standard.qhelp +++ b/cpp/cert/src/rules/MEM56-CPP/OwnedPointerValueStoredInUnrelatedSmartPointerCert-standard.qhelp @@ -1,33 +1,200 @@
    -

    Smart pointers such as std::unique_ptr and std::shared_ptr encode pointer ownership semantics as part of the type system. They wrap a pointer value, provide pointer-like semantics through operator *() and operator->() member functions, and control the lifetime of the pointer they manage. When a smart pointer is constructed from a pointer value, that value is said to be owned by the smart pointer.

    -

    Calling std::unique_ptr::release() will relinquish ownership of the managed pointer value. Destruction of, move assignment of, or calling std::unique_ptr::reset() on a std::unique_ptr object will also relinquish ownership of the managed pointer value, but results in destruction of the managed pointer value. If a call to std::shared_ptr::unique() returns true, then destruction of or calling std::shared_ptr::reset() on that std::shared_ptr object will relinquish ownership of the managed pointer value but results in destruction of the managed pointer value.

    -

    Some smart pointers, such as std::shared_ptr, allow multiple smart pointer objects to manage the same underlying pointer value. In such cases, the initial smart pointer object owns the pointer value, and subsequent smart pointer objects are related to the original smart pointer. Two smart pointers are related when the initial smart pointer is used in the initialization of the subsequent smart pointer objects. For instance, copying a std::shared_ptr object to another std::shared_ptr object via copy assignment creates a relationship between the two smart pointers, whereas creating a std::shared_ptr object from the managed pointer value of another std::shared_ptr object does not.

    -

    Do not create an unrelated smart pointer object with a pointer value that is owned by another smart pointer object. This includes resetting a smart pointer's managed pointer to an already-owned pointer value, such as by calling reset().

    +

    + Smart pointers such as + + std::unique_ptr + + and + + std::shared_ptr + + encode pointer ownership semantics as part of the type system. They wrap a pointer value, provide pointer-like semantics through + + operator *() + + and + + operator->() + + member functions, and control the lifetime of the pointer they manage. When a smart pointer is constructed from a pointer value, that value is said to be + + owned + + by the smart pointer. +

    +

    + Calling + + std::unique_ptr::release() + + will relinquish ownership of the managedย pointer value. Destruction of, move assignment of, or calling + + std::unique_ptr::reset() + + on a + + std::unique_ptr + + object will also relinquish ownership of the managedย pointer value, but results in destruction of the managedย pointer value. If a call to + + std::shared_ptr::unique() + + returns true, then destruction of or calling + + std::shared_ptr::reset() + + on that + + std::shared_ptr + + object will relinquish ownership of the managedย pointer value but results in destruction of the managedย pointer value. +

    +

    + Some smart pointers, such as + + std::shared_ptr + + , allow multiple smart pointer objects to manage the same underlying pointer value. In such cases, the initial smart pointer object owns the pointer value, and subsequent smart pointer objects are relatedย to the original smart pointer. Two smart pointers are + + related + + when the initial smart pointer is used in the initialization of the subsequent smart pointer objects. For instance, copying a + + std::shared_ptr + + object to another + + std::shared_ptr + + object via copy assignment creates a relationship between the two smart pointers, whereas creating a + + std::shared_ptr + + object from the managed pointer value of another + + std::shared_ptr + + object does not. +

    +

    + Do not create an unrelated smart pointer object with a pointer value that isย owned by another smart pointer object. This includes resetting a smart pointer's managed pointer to an already-owned pointer value, such as by calling + + reset() + + . +

    -

    In this noncompliant code example, two unrelated smart pointers are constructed from the same underlying pointer value. When the local, automatic variable p2 is destroyed, it deletes the pointer value it manages. Then, when the local, automatic variable p1 is destroyed, it deletes the same pointer value, resulting in a double-free vulnerability.

    - #include <memory> +

    + In this noncompliant code example, two unrelated smart pointers are constructed from the same underlying pointer value. When the local, automatic variable + + p2 + + is destroyed, it deletes the pointer value it manages. Then, when the local, automatic variable + + p1 + + is destroyed, it deletes the same pointer value, resulting in a double-free + + vulnerability + + . +

    + + #include <memory> void f() { int *i = new int; std::shared_ptr<int> p1(i); std::shared_ptr<int> p2(i); -} +} +
    -

    In this compliant solution, the std::shared_ptr objects are related to one another through copy construction. When the local, automatic variable p2 is destroyed, the use count for the shared pointer value is decremented but still nonzero. Then, when the local, automatic variable p1 is destroyed, the use count for the shared pointer value is decremented to zero, and the managed pointer is destroyed. This compliant solution also calls std::make_shared() instead of allocating a raw pointer and storing its value in a local variable.

    - #include <memory> +

    + In this compliant solution, the + + std::shared_ptr + + objects are related to one another through copy construction. When the local, automatic variable + + p2 + + is destroyed, the use count for the shared pointer value is decremented but still nonzero. Then, when the local, automatic variable + + p1 + + is destroyed, the use count for the shared pointer value is decremented to zero, and the managed pointer is destroyed. This compliant solution also calls + + std::make_shared + + () instead of allocating a raw pointer and storing its value in a local variable. +

    + + #include <memory> void f() { std::shared_ptr<int> p1 = std::make_shared<int>(); std::shared_ptr<int> p2(p1); -} +} +
    -

    In this noncompliant code example, the poly pointer value owned by a std::shared_ptr object is cast to the D * pointer type with dynamic_cast in an attempt to obtain a std::shared_ptr of the polymorphic derived type. However, this eventually results in undefined behavior as the same pointer is thereby stored in two different std::shared_ptr objects. When g() exits, the pointer stored in derived is freed by the default deleter. Any further use of poly results in accessing freed memory. When f() exits, the same pointer stored in poly is destroyed, resulting in a double-free vulnerability.

    - #include <memory> +

    + In this noncompliant code example, the + + poly + + pointer value owned by a + + std::shared_ptr + + object is cast to the + + D * + + pointer type with + + dynamic_cast + + in an attempt to obtain a + + std::shared_ptr + + of the polymorphic derived type. However, this eventually results in + + undefined behavior + + as the same pointer is thereby stored in two different + + std::shared_ptr + + objects. When + + g() + + exits, the pointer stored in + + derived + + is freed by the default deleter. Any further use of + + poly + + results in accessing freed memory. When + + f() + + exits, the same pointer stored in + + poly + + is destroyed, resulting in a double-free vulnerability. +

    + + #include <memory> struct B { virtual ~B() = default; // Polymorphic object @@ -42,11 +209,47 @@ void f() { // ... g(std::shared_ptr<D>(dynamic_cast<D *>(poly.get()))); // Any use of poly will now result in accessing freed memory. -} +} +
    -

    In this compliant solution, the dynamic_cast is replaced with a call to std::dynamic_pointer_cast(), which returns a std::shared_ptr of the polymorphic type with the valid shared pointer value. When g() exits, the reference count to the underlying pointer is decremented by the destruction of derived, but because of the reference held by poly (within f()), the stored pointer value is still valid after g() returns.

    - #include <memory> +

    + In this compliant solution, the + + dynamic_cast + + is replaced with a call to + + std::dynamic_pointer_cast() + + , which returns a + + std::shared_ptr + + of the polymorphic type with the valid shared pointer value. When + + g() + + exits, the reference count to the underlying pointer is decremented by the destruction of + + derived + + , but because of the reference held by + + poly + + (within + + f() + + ), the stored pointer value is still valid after + + g() + + returns. +

    + + #include <memory> struct B { virtual ~B() = default; // Polymorphic object @@ -61,11 +264,55 @@ void f() { // ... g(std::dynamic_pointer_cast<D, B>(poly)); // poly is still referring to a valid pointer value. -} +} +
    -

    In this noncompliant code example, a std::shared_ptr of type S is constructed and stored in s1. Later, S::g() is called to get another shared pointer to the pointer value managed by s1. However, the smart pointer returned by S::g() is not related to the smart pointer stored in s1. When s2 is destroyed, it will free the pointer managed by s1, causing a double-free vulnerability when s1 is destroyed.

    - #include <memory> +

    + In this noncompliant code example, a + + std::shared_ptr + + of type + + S + + is constructed and stored in + + s1 + + . Later, + + S::g() + + is called to get another shared pointer toย the pointer value managed by + + s1 + + . However, the smart pointer returned by + + S::g() + + is not related to the smart pointer stored in + + s1 + + . When + + s2 + + is destroyed, it will free the pointer managed by + + s1 + + , causing a double-free vulnerability when + + s1 + + is destroyed. +

    + + #include <memory> struct S { std::shared_ptr<S> g() { return std::shared_ptr<S>(this); } @@ -75,11 +322,55 @@ void f() { std::shared_ptr<S> s1 = std::make_shared<S>(); // ... std::shared_ptr<S> s2 = s1->g(); -} +} +
    -

    The compliant solution is to use std::enable_shared_from_this::shared_from_this() to get a shared pointer from S that is related to an existing std::shared_ptr object. A common implementation strategy is for the std::shared_ptr constructors to detect the presence of a pointer that inherits from std::enable_shared_from_this, and automatically update the internal bookkeeping required for std::enable_shared_from_this::shared_from_this() to work. Note that std::enable_shared_from_this::shared_from_this() requires an existing std::shared_ptr instance that manages the pointer value pointed to by this. Failure to meet this requirement results in undefined behavior, as it would result in a smart pointer attempting to manage the lifetime of an object that itself does not have lifetime management semantics.

    - #include <memory> +

    + The compliant solution is to use + + std::enable_shared_from_this::shared_from_this() + + to get a shared pointer from + + S + + that is related to an existing + + std::shared_ptr + + object. A common implementation strategy is for the + + std::shared_ptr + + constructors to detect the presence of a pointer that inherits from + + std::enable_shared_from_this + + , and automatically update the internal bookkeeping required for + + std::enable_shared_from_this::shared_from_this() + + to work. Note that + + std::enable_shared_from_this::shared_from_this() + + requires an existing + + std::shared_ptr + + instance that manages the pointer value pointed to by + + this + + . Failure to meet this requirement results in + + undefined behavior + + , as it would result in a smart pointer attempting to manage the lifetime of an object that itself does not have lifetime management semantics. +

    + + #include <memory> struct S : std::enable_shared_from_this<S> { std::shared_ptr<S> g() { return shared_from_this(); } @@ -88,10 +379,21 @@ struct S : std::enable_shared_from_this<S> { void f() { std::shared_ptr<S> s1 = std::make_shared<S>(); std::shared_ptr<S> s2 = s1->g(); -} +} +
    -

    Passing a pointer value to a deallocation function that was not previously obtained by the matching allocation function results in undefined behavior, which can lead to exploitable vulnerabilities.

    +

    + Passing a pointer value to a deallocation function that was not previously obtained by the matching allocation function results in + + undefined behavior + + , which can lead to exploitable + + vulnerabilities + + . +

    @@ -128,10 +430,14 @@ void f() { Medium @@ -164,7 +470,9 @@ void f() { 20.10 @@ -179,7 +487,9 @@ void f() { 7.2.0 @@ -194,7 +504,9 @@ void f() { 2021.2 @@ -209,7 +521,9 @@ void f() { 2021.2 @@ -252,7 +570,17 @@ void f() {
    - P18 + + P18 + - L1 + + L1 +
    - dangling_pointer_use + + dangling_pointer_use + - CertC++-MEM56 + + CertC++-MEM56 + - C++4721, C++4722, C++4723 + + C++4721, C++4722, C++4723 + - CERT_CPP-MEM56-a + + CERT_CPP-MEM56-a + Do not store an already-owned pointer value in an unrelated smart pointer @@ -240,10 +554,14 @@ void f() { - 7.17 + 7.16 - V1006 + + + V1006 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes-standard.qhelp b/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes-standard.qhelp index a3af8293ff..e878a67751 100644 --- a/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes-standard.qhelp +++ b/cpp/cert/src/rules/MEM57-CPP/UsingDefaultOperatorNewForOverAlignedTypes-standard.qhelp @@ -1,24 +1,121 @@
    -

    The non-placement new expression is specified to invoke an allocation function to allocate storage for an object of the specified type. When successful, the allocation function, in turn, is required to return a pointer to storage with alignment suitable for any object with a fundamental alignment requirement. Although the global operator new, the default allocation function invoked by the new expression, is specified by the C++ standard [ISO/IEC 14882-2014] to allocate sufficient storage suitably aligned to represent any object of the specified size, since the expected alignment isn't part of the function's interface, the most a program can safely assume is that the storage allocated by the default operator new defined by the implementation is aligned for an object with a fundamental alignment. In particular, it is unsafe to use the storage for an object of a type with a stricter alignment requirementโ€”an over-aligned type.

    -

    Furthermore, the array form of the non-placement new expression may increase the amount of storage it attempts to obtain by invoking the corresponding allocation function by an unspecified amount. This amount, referred to as overhead in the C++ standard, is commonly known as a cookie. The cookie is used to store the number of elements in the array so that the array delete expression or the exception unwinding mechanism can invoke the type's destructor on each successfully constructed element of the array. While the specific conditions under which the cookie is required by the array new expression aren't described in the C++ standard, they may be outlined in other specifications such as the application binary interface (ABI) document for the target environment. For example, the Itanium C++ ABI describes the rules for computing the size of a cookie, its location, and achieving the correct alignment of the array elements. When these rules require that a cookie be created, it is possible to obtain a suitably aligned array of elements of an overaligned type [CodeSourcery 2016a]. However, the rules are complex and the Itanium C++ ABI isn't universally applicable.

    -

    Avoid relying on the default operator new to obtain storage for objects of over-aligned types. Doing so may result in an object being constructed at a misaligned location, which has undefined behavior and can result in abnormal termination when the object is accessed, even on architectures otherwise known to tolerate misaligned accesses.

    +

    + The non-placement + + new + + expression is specified to invoke an allocation function to allocate storage for an object of the specified type. When successful, the allocation function, in turn, is required to return a pointer to storage with alignment suitable for any object with a fundamental alignment requirement. Although the global + + operator new + + , the default allocation function invoked by the new expression, is specified by the C++ standard [ + + ISO/IEC 14882-2014 + + ] to allocate sufficient storage suitably aligned to represent any object of the specified size, since the expected alignment isn't part of the function's interface, the most a program can safely assume is that the storage allocated by the default + + operator new + + defined by the implementation is aligned for an object with a fundamental alignment. In particular, it is unsafe to use the storage for an object of a type with a stricter alignment requirementโ€”an + + over-aligned type + + . +

    +

    + Furthermore, the array form of the non-placement + + new + + expression may increase the amount of storage it attempts to obtain by invoking the corresponding allocation function by an unspecified amount. This amount, referred to as overhead in the C++ standard, is commonly known as a + + cookie + + . The cookie is used to store the number of elements in the array so that the array delete expression or the exception unwinding mechanism can invoke the type's destructor on each successfully constructed element of the array. While the specific conditions under which the cookie is required by the array new expression aren't described in the C++ standard, they may be outlined in other specifications such as the + + application binary interface + + (ABI) document for the target environment. For example, the Itanium C++ ABI describes the rules for computing the size of a cookie, its location, and achieving the correct alignment of the array elements. When these rules require that a cookie be created, it is possible to obtain a suitably aligned array of elements of an overaligned type [ + + CodeSourcery 2016a + + ]. However, the rules are complex and the Itanium C++ ABI isn't universally applicable. +

    +

    + Avoid relying on the default + + operator new + + to obtain storage for objects of over-aligned types. Doing so may result in an object being constructed at a misaligned location, which has + + undefined behavior + + and can result in + + abnormal termination + + when the object is accessed, even on architectures otherwise known to tolerate misaligned accesses. +

    -

    In the following noncompliant code example, the new expression is used to invoke the default operator new to obtain storage in which to then construct an object of the user-defined type Vector with alignment that exceeds the fundamental alignment of most implementations (typically 16 bytes). Objects of such over-aligned types are typically required by SIMD (single instruction, multiple data) vectorization instructions, which can trap when passed unsuitably aligned arguments.

    - struct alignas(32) Vector { +

    + In the following noncompliant code example, the new expression is used to invoke the default + + operator new + + to obtain storage in which to then construct an object of the user-defined type + + Vector + + with alignment that exceeds the fundamental alignment of most implementations (typically 16 bytes). Objects of such over-aligned types are typically required by SIMD (single instruction, multiple data)ย vectorization instructions, which can trap when passed unsuitably aligned arguments. +

    + + struct alignas(32) Vector { char elems[32]; }; Vector *f() { Vector *pv = new Vector; return pv; -} +} +
    -

    In this compliant solution, an overloaded operator new function is defined to obtain appropriately aligned storage by calling the C11 function aligned_alloc(). Programs that make use of the array form of the new expression must define the corresponding member array operator new[] and operator delete[]. The aligned_alloc() function is not part of the C++ 98, C++ 11, or C++ 14 standards but may be provided by implementations of such standards as an extension. Programs targeting C++ implementations that do not provide the C11 aligned_alloc() function must define the member operator new to adjust the alignment of the storage obtained by the allocation function of their choice.

    - #include <cstdlib> +

    + In this compliant solution, an overloaded + + operator new + + function is defined to obtain appropriately aligned storage by calling the C11 function + + aligned_alloc() + + . Programs that make use of the array form of the new expression must define the corresponding member array + + operator new[] + + and + + operator delete[] + + . The + + aligned_alloc() + + function is not part of the C++ 98, C++ 11, or C++ 14 standards but may be provided by implementations of such standards as an extension. Programs targeting C++ implementations that do not provide the C11 + + aligned_alloc() + + function must define the member + + operator new + + to adjust the alignment of the storage obtained by the allocation function of their choice. +

    + + #include <cstdlib> #include <new> struct alignas(32) Vector { @@ -37,10 +134,21 @@ struct alignas(32) Vector { Vector *f() { Vector *pv = new Vector; return pv; -} +} +
    -

    Using improperly aligned pointers results in undefined behavior, typically leading to abnormal termination.

    +

    + Using improperly aligned pointers results in + + undefined behavior + + , typically leading to + + abnormal termination + + . +

    @@ -77,10 +185,14 @@ Vector *f() { Low @@ -113,7 +225,9 @@ Vector *f() { 2021.2 @@ -128,7 +242,9 @@ Vector *f() { 2021.2
    - P6 + + P6 + - L2 + + L2 +
    - C++3129 + + C++3129 + - CERT_CPP-MEM57-a + + CERT_CPP-MEM57-a + Avoid using the default operator 'new' for over-aligned types @@ -156,7 +272,17 @@ Vector *f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers-standard.qhelp b/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers-standard.qhelp index a6312aa07e..c0ff5fbe4c 100644 --- a/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers-standard.qhelp +++ b/cpp/cert/src/rules/MSC50-CPP/DoNotUseRandForGeneratingPseudorandomNumbers-standard.qhelp @@ -1,26 +1,65 @@
    -

    Pseudorandom number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random.

    -

    The C Standard rand() function, exposed through the C++ standard library through <cstdlib> as std::rand(), makes no guarantees as to the quality of the random sequence produced. The numbers generated by some implementations of std::rand() have a comparatively short cycle, and the numbers can be predictable. Applications that have strong pseudorandom number requirements must use a generator that is known to be sufficient for their needs.

    +

    + Pseudorandom number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random. +

    +

    + The C Standard + + rand() + + function, exposed through the C++ standard library through + + <cstdlib> + + as + + std::rand() + + , makes no guarantees as to the quality of the random sequence produced. The numbers generated by some implementations of + + std::rand() + + have a comparatively short cycle, and the numbers can be predictable.ย Applications that have strong pseudorandom number requirements must use a generator that is known to be sufficient for their needs. +

    -

    The following noncompliant code generates an ID with a numeric part produced by calling the rand() function. The IDs produced are predictable and have limited randomness. Further, depending on the value of RAND_MAX, the resulting value can have modulo bias.

    - #include <cstdlib> +

    + The following noncompliant code generates an ID with a numeric part produced by calling the + + rand() + + function. The IDs produced are predictable and have limited randomness. Further, depending on the value of + + RAND_MAX + + , the resulting value can have modulo bias. +

    + + #include <cstdlib> #include <string> - +ย  void f() { std::string id("ID"); // Holds the ID, starting with the characters "ID" followed // by a random integer in the range [0-10000]. id += std::to_string(std::rand() % 10000); // ... -} +} +
    -

    The C++ standard library provides mechanisms for fine-grained control over pseudorandom number generation. It breaks random number generation into two parts: one is the algorithm responsible for providing random values (the engine), and the other is responsible for distribution of the random values via a density function (the distribution). The distribution object is not strictly required, but it works to ensure that values are properly distributed within a given range instead of improperly distributed due to bias issues. This compliant solution uses the Mersenne Twister algorithm as the engine for generating random values and a uniform distribution to negate the modulo bias from the noncompliant code example.

    - #include <random> +

    + The C++ standard library provides mechanisms for fine-grained control over pseudorandomย number generation. It breaks random number generation into two parts: one is the algorithm responsible for providing random values (the engine), and the other is responsible for distribution of the random values via a density function (the distribution). The distribution object is not strictly required, but it works to ensure that values are properly distributed within a given range instead of improperly distributed due to bias issues. This compliant solution uses the + + Mersenne Twister + + algorithm as the engine for generating random values and a uniform distribution to negate the modulo bias from the noncompliant code example. +

    + + #include <random> #include <string> - +ย  void f() { std::string id("ID"); // Holds the ID, starting with the characters "ID" followed // by a random integer in the range [0-10000]. @@ -30,11 +69,23 @@ void f() { id += std::to_string(distribution(engine)); // ... } - -

    This compliant solution also seeds the random number engine, in conformance with MSC51-CPP. Ensure your random number generator is properly seeded.

    +
    +

    + This compliant solution also seeds the random number engine, in conformance with + + MSC51-CPP. Ensure your random number generator is properly seeded + + . +

    -

    Using the std::rand() function could lead to predictable random numbers.

    +

    + Using the + + std::rand() + + function could lead to predictable random numbers. +

    @@ -71,10 +122,14 @@ void f() { Low @@ -107,7 +162,9 @@ void f() { 20.10 @@ -138,11 +197,15 @@ void f() { 4.0 (prerelease) @@ -152,14 +215,18 @@ void f() { @@ -185,7 +252,9 @@ void f() { 1.2 @@ -216,7 +287,11 @@ void f() { 2021.4 @@ -230,7 +305,9 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - bad-function (AUTOSAR.26.5.1A) + + bad-function (AUTOSAR.26.5.1A) + Fully checked @@ -123,7 +180,9 @@ void f() { 7.2.0 - CertC++-MSC50 + + CertC++-MSC50 + - cert-msc50-cpp + + cert-msc50-cpp + Checked by - clang-tidy + + clang-tidy +
    - 6.2p0 + 6.1p0 - BADFUNC.RANDOM.RAND + + BADFUNC.RANDOM.RAND + Use of - rand + + rand +
    - CC2.MSC30 + + CC2.MSC30 + Fully implemented @@ -201,7 +270,9 @@ void f() { 2021.2 - C++5028 + + C++5028 + - CERT.MSC.STD_RAND_CALL + + + CERT.MSC.STD_RAND_CALL + + - 44 S + + 44 S + Enhanced Enforcement @@ -246,7 +323,9 @@ void f() { 2021.2 - CERT_CPP-MSC50-a + + CERT_CPP-MSC50-a + Do not use the rand() function for generating pseudorandom numbers @@ -280,7 +359,9 @@ void f() { 4.4 - 5028 + + 5028 + Fully implemented @@ -296,7 +377,9 @@ void f() { 20.10 - bad-function (AUTOSAR.26.5.1A) + + bad-function (AUTOSAR.26.5.1A) + Fully checked @@ -306,7 +389,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator-standard.qhelp b/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator-standard.qhelp index db310805fd..72c3003df2 100644 --- a/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator-standard.qhelp +++ b/cpp/cert/src/rules/MSC51-CPP/BadlySeededRandomNumberGenerator-standard.qhelp @@ -1,15 +1,48 @@
    -

    A pseudorandom number generator (PRNG) is a deterministic algorithm capable of generating sequences of numbers that approximate the properties of random numbers. Each sequence is completely determined by the initial state of the PRNG and the algorithm for changing the state. Most PRNGs make it possible to set the initial state, also called the seed state. Setting the initial state is called seeding the PRNG.

    -

    Calling a PRNG in the same initial state, either without seeding it explicitly or by seeding it with a constant value, results in generating the same sequence of random numbers in different runs of the program. Consider a PRNG function that is seeded with some initial seed value and is consecutively called to produce a sequence of random numbers. If the PRNG is subsequently seeded with the same initial seed value, then it will generate the same sequence.

    -

    Consequently, after the first run of an improperly seeded PRNG, an attacker can predict the sequence of random numbers that will be generated in the future runs. Improperly seeding or failing to seed the PRNG can lead to vulnerabilities, especially in security protocols.

    -

    The solution is to ensure that a PRNG is always properly seeded with an initial seed value that will not be predictable or controllable by an attacker. A properly seeded PRNG will generate a different sequence of random numbers each time it is run.

    -

    Not all random number generators can be seeded. True random number generators that rely on hardware to produce completely unpredictable results do not need to be and cannot be seeded. Some high-quality PRNGs, such as the /dev/random device on some UNIX systems, also cannot be seeded. This rule applies only to algorithmic PRNGs that can be seeded.

    +

    + A pseudorandom number generator (PRNG) is a deterministic algorithm capable of generating sequences of numbers that approximate the properties of random numbers. Each sequence is completely determined by the initial state of the PRNG and the algorithm for changing the state. Most PRNGs make it possible to set the initial state, alsoย called the + + seed state + + . Setting the initial state is called + + seeding + + the PRNG. +

    +

    + Calling a PRNG in the same initial state, either without seeding it explicitly or by seeding it with a constant value, results in generating the same sequence of random numbers in different runs of the program. Consider a PRNG function that is seeded with some initial seed value and is consecutively called to produce a sequence of random numbers.ย If the PRNG is subsequently seeded with the same initial seed value, then it will generate the same sequence. +

    +

    + Consequently, after the first run of an improperly seeded PRNG, an attacker can predict the sequence of random numbers that will be generated in the future runs.ย Improperly seeding or failing to seed the PRNGย can lead to + + vulnerabilities + + , especially in security protocols. +

    +

    + The solution is to ensure that a PRNG is always properly seeded with anย initial seed value that will not be predictable or controllable by an attacker. A properly seeded PRNG will generate a different sequence of random numbers each time it is run. +

    +

    + Not all random number generators can be seeded. True random number generators that rely on hardware to produce completely unpredictable results do not need to be and cannot be seeded. Some high-quality PRNGs, such as the + + /dev/random + + device on some UNIX systems, also cannot be seeded. This rule applies only to algorithmic PRNGs that can be seeded. +

    -

    This noncompliant code example generates a sequence of 10 pseudorandom numbers using the Mersenne Twister engine. No matter how many times this code is executed, it always produces the same sequence because the default seed is used for the engine.

    - #include <random> +

    + This noncompliant code example generates a sequence of 10 pseudorandom numbers using the + + Mersenne Twister + + engine. No matter how many times this code is executed, it always produces the same sequence because the default seed is used for the engine. +

    + + #include <random> #include <iostream> void f() { @@ -18,16 +51,28 @@ void f() { for (int i = 0; i < 10; ++i) { std::cout << engine() << ", "; } -} -

    The output of this example follows.

    - 1st run: 3499211612, 581869302, 3890346734, 3586334585, 545404204, 4161255391, 3922919429, 949333985, 2715962298, 1323567403, +} + +

    + The output of this example follows. +

    + + 1st run: 3499211612, 581869302, 3890346734, 3586334585, 545404204, 4161255391, 3922919429, 949333985, 2715962298, 1323567403, 2nd run: 3499211612, 581869302, 3890346734, 3586334585, 545404204, 4161255391, 3922919429, 949333985, 2715962298, 1323567403, ... -nth run: 3499211612, 581869302, 3890346734, 3586334585, 545404204, 4161255391, 3922919429, 949333985, 2715962298, 1323567403, +nth run: 3499211612, 581869302, 3890346734, 3586334585, 545404204, 4161255391, 3922919429, 949333985, 2715962298, 1323567403, +
    -

    This noncompliant code example improves the previous noncompliant code example by seeding the random number generation engine with the current time. However, this approach is still unsuitable when an attacker can control the time at which the seeding is executed. Predictable seed values can result in exploits when the subverted PRNG is used.

    - #include <ctime> +

    + This noncompliant code example improves the previous noncompliant code example by seeding the random number generation engine with the current time. However, this approach is still unsuitable when an attacker can control the time at which the seeding is executed. Predictable seed values can result in + + exploits + + when the subverted PRNG is used. +

    + + #include <ctime> #include <random> #include <iostream> @@ -38,11 +83,31 @@ void f() { for (int i = 0; i < 10; ++i) { std::cout << engine() << ", "; } -} +} +
    -

    This compliant solution uses std::random_device to generate a random value for seeding the Mersenne Twister engine object. The values generated by std::random_device are nondeterministic random numbers when possible, relying on random number generation devices, such as /dev/random. When such a device is not available, std::random_device may employ a random number engine; however, the initial value generated should have sufficient randomness to serve as a seed value.

    - #include <random> +

    + This compliant solution uses + + std::random_device + + to generate a random value for seeding the Mersenne Twister engine object. The values generated by + + std::random_device + + are nondeterministic random numbers when possible, relying on random number generation devices, such as + + /dev/random + + . When such a device is not available, + + std::random_device + + may employ a random number engine; however, the initial value generated should have sufficient randomness to serve as a seed value. +

    + + #include <random> #include <iostream> void f() { @@ -52,12 +117,17 @@ void f() { for (int i = 0; i < 10; ++i) { std::cout << engine() << ", "; } -} -

    The output of this example follows.

    - 1st run: 3921124303, 1253168518, 1183339582, 197772533, 83186419, 2599073270, 3238222340, 101548389, 296330365, 3335314032, +} + +

    + The output of this example follows. +

    + + 1st run: 3921124303, 1253168518, 1183339582, 197772533, 83186419, 2599073270, 3238222340, 101548389, 296330365, 3335314032, 2nd run: 2392369099, 2509898672, 2135685437, 3733236524, 883966369, 2529945396, 764222328, 138530885, 4209173263, 1693483251, 3rd run: 914243768, 2191798381, 2961426773, 3791073717, 2222867426, 1092675429, 2202201605, 850375565, 3622398137, 422940882, -... +... +
    @@ -96,10 +166,14 @@ void f() { Low @@ -132,7 +206,9 @@ void f() { 20.10 @@ -163,7 +241,9 @@ void f() { 2021.2 @@ -184,7 +264,7 @@ void f() { @@ -198,7 +278,9 @@ void f() { 2021.2 @@ -229,7 +315,9 @@ void f() { 20.10
    - P18 + + P18 + - L1 + + L1 +
    - default-construction + + default-construction + Partially checked @@ -148,7 +224,9 @@ void f() { 7.2.0 - CertC++-MSC51 + + CertC++-MSC51 + - C++5041 + + C++5041 + Checks for: - Deterministic random output from constant seedeterministic random output from constant seed, predictable random output from predictable seedredictable random output from predictable seed. + Deterministic random output from constant seed, predictable random output from predictable seed. Rule partially covered.
    - CERT_CPP-MSC51-a + + CERT_CPP-MSC51-a + Properly seed pseudorandom number generators @@ -211,10 +293,14 @@ void f() { - 7.17 + 7.16 - V1057 + + + V1057 + + - default-construction + + default-construction + Partially checked @@ -239,8 +327,24 @@ void f() {
    -

    Using a predictable seed value, such as the current time, result in numerous vulnerabilities, such as the one described by CVE-2008-1637.

    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Using a predictable seed value, such as the current time, result in numerous + + vulnerabilities + + , such as the one described by + + CVE-2008-1637 + + . +

    +

    + Search for vulnerabilities resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert-standard.qhelp b/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert-standard.qhelp index 954acafa2a..4e98217391 100644 --- a/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert-standard.qhelp +++ b/cpp/cert/src/rules/MSC52-CPP/NonVoidFunctionDoesNotReturnCert-standard.qhelp @@ -1,58 +1,154 @@
    -

    The C++ Standard, [stmt.return], paragraph 2 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [stmt.return], paragraph 2 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

    +

    + Flowing off the end of a function is equivalent to a + + return + + with no value; this results in undefinedย behavior in a value-returning function. +

    -

    A value-returning function must return a value from all code paths; otherwise, it will result in undefined behavior. This includes returning through less-common code paths, such as from a function-try-block, as explained in the C++ Standard, [except.handle], paragraph 15:

    +

    + A value-returning function must return a value from all code paths; otherwise, it will result in + + undefined behavior + + . This includes returning through less-common code paths, such as from a + + + function-try-block + + + , as explained in the C++ Standard,ย [except.handle], paragraph 15: +

    -

    Flowing off the end of a function-try-block is equivalent to a return with no value; this results in undefined behavior in a value-returning function (6.6.3).

    +

    + Flowing off the end of a + + function-try-block + + is equivalent to a + + return + + with noย value; this results in undefined behavior in a value-returning function (6.6.3). +

    -

    In this noncompliant code example, the programmer forgot to return the input value for positive input, so not all code paths return a value.

    - int absolute_value(int a) { +

    + In this noncompliant code example,ย the programmer forgot to return the input value for positive input, soย not all code paths return a value. +

    + + int absolute_value(int a) { if (a < 0) { return -a; } -} +} +
    -

    In this compliant solution, all code paths now return a value.

    - int absolute_value(int a) { +

    + In this compliant solution, all code paths now return a value. +

    + + int absolute_value(int a) { if (a < 0) { return -a; } return a; -} +} +
    -

    In this noncompliant code example, the function-try-block handler does not return a value, resulting in undefined behavior when an exception is thrown.

    - #include <vector> +

    + In this noncompliant code example, the + + function-try-block + + handler does not return a value, resulting in + + undefined behavior + + when an exception is thrown. +

    + + #include <vector> std::size_t f(std::vector<int> &v, std::size_t s) try { v.resize(s); return s; } catch (...) { } - +
    -

    In this compliant solution, the exception handler of the function-try-block also returns a value.

    - #include <vector> +

    + In this compliant solution, the exception handler of the + + function-try-block + + also returns a value. +

    + + #include <vector> std::size_t f(std::vector<int> &v, std::size_t s) try { v.resize(s); return s; } catch (...) { return 0; -} +} +
    -

    MSC54-CPP-EX1: Flowing off the end of the main() function is equivalent to a return 0; statement, according to the C++ Standard, [basic.start.main], paragraph 5 [ISO/IEC 14882-2014]. Thus, flowing off the end of the main() function does not result in undefined behavior.

    -

    MSC54-CPP-EX2: It is permissible for a control path to not return a value if that code path is never expected to be taken and a function marked [[noreturn]] is called as part of that code path or if an exception is thrown, as is illustrated in the following code example.

    - #include <cstdlib> +

    + + MSC54-CPP-EX1: + + Flowing off the end of the + + main() + + function is equivalent to a + + return 0; + + statement, according to the C++ Standard,ย [basic.start.main], paragraph 5 [ + + ISO/IEC 14882-2014 + + ]. ย Thus, flowing off the end of the + + main() + + functionย does not result in + + undefined behavior + + . +

    +

    + + MSC54-CPP-EX2: + + It is permissible for a control path to not return a value if that code path is never expected to be taken and a function marked + + [[noreturn]] + + is called as part of that code path or if an exception is thrown, as is illustrated in the following code example. +

    + + #include <cstdlib> #include <iostream> [[noreturn]] void unreachable(const char *msg) { std::cout << "Unreachable code reached: " << msg << std::endl; @@ -72,10 +168,21 @@ int f(E e) { case Three: return 3; } unreachable("Can never get here"); -} +} +
    -

    Failing to return a value from a code path in a value-returning function results in undefined behavior that might be exploited to cause data integrity violations.

    +

    + Failing to return a value from a code path in a value-returning function results in + + undefined behavior + + that might be + + exploited + + to cause data integrity violations. +

    @@ -112,10 +219,14 @@ int f(E e) { Medium @@ -148,7 +259,9 @@ int f(E e) { 20.10 @@ -179,7 +294,9 @@ int f(E e) { 3.9 @@ -229,8 +350,12 @@ int f(E e) { 2021.4 @@ -244,7 +369,9 @@ int f(E e) { @@ -309,7 +442,9 @@ int f(E e) { 4.4 @@ -321,10 +456,14 @@ int f(E e) { @@ -339,7 +478,9 @@ int f(E e) { 20.10
    - P8 + + P8 + - L2 + + L2 +
    - return-implicit + + return-implicit + Fully checked @@ -164,7 +277,9 @@ int f(E e) { 7.2.0 - CertC++-MSC52 + + CertC++-MSC52 + - -Wreturn-type + + -Wreturn-type + Does not catch all instances of this rule, such as @@ -195,10 +312,12 @@ int f(E e) { - 6.2p0 + 6.1p0 - LANG.STRUCT.MRS + + LANG.STRUCT.MRS + Missing return statement @@ -214,7 +333,9 @@ int f(E e) { 2021.2 - C++2888 + + C++2888 + - FUNCRET.GEN - FUNCRET.IMPLICIT + + FUNCRET.GEN + + + FUNCRET.IMPLICIT + - 2 D, 36 S + + 2 D, 36 S + Fully implemented @@ -260,7 +387,9 @@ int f(E e) { 2021.2 - CERT_CPP-MSC52-a + + CERT_CPP-MSC52-a + All exit paths from a function with non-void return type shall have an explicit return statement with an expression @@ -294,7 +423,11 @@ int f(E e) { 4.10 - S935 + + + S935 + + - 1510 + + 1510 + - 7.17 + 7.16 - V591 + + + V591 + + - return-implicit + + return-implicit + Fully checked @@ -349,7 +490,17 @@ int f(E e) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -365,7 +516,9 @@ int f(E e) { diff --git a/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert-standard.qhelp b/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert-standard.qhelp index bf7bfede31..812c817f12 100644 --- a/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert-standard.qhelp +++ b/cpp/cert/src/rules/MSC53-CPP/FunctionNoReturnAttributeConditionCert-standard.qhelp @@ -1,35 +1,104 @@
    -

    The [[noreturn]] attribute specifies that a function does not return. The C++ Standard, [dcl.attr.noreturn] paragraph 2 [ISO/IEC 14882-2014], states the following:

    +

    + The + + [[noreturn]] + + attribute specifies that a function does not return. The C++ Standard,ย [dcl.attr.noreturn] paragraph 2 + [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    If a function f is called where f was previously declared with the noreturn attribute and f eventually returns, the behavior is undefined.

    +

    + If a function + + f + + is called where + + f + + was previously declared with the + + noreturn + + attribute and + + f + + eventuallyย returns, the behavior is undefined. +

    -

    A function that specifies [[noreturn]] can prohibit returning by throwing an exception, entering an infinite loop, or calling another function designated with the [[noreturn]] attribute.

    +

    + Aย function that specifies + + [[noreturn]] + + can prohibit returning by throwing an exception, entering an infinite loop, or calling another function designated with the + + [[noreturn]] + + attribute. +

    -

    In this noncompliant code example, if the value 0 is passed, control will flow off the end of the function, resulting in an implicit return and undefined behavior.

    - #include <cstdlib> - +

    + In this noncompliant code example, if the value + + 0 + + is passed, control will flow off the end of the function, resulting in an implicit return and + + undefined behavior + + . +

    + + #include <cstdlib> +ย  [[noreturn]] void f(int i) { if (i > 0) throw "Received positive input"; else if (i < 0) std::exit(0); -} +} +
    -

    In this compliant solution, the function does not return on any code path.

    - #include <cstdlib> - +

    + In this compliant solution, the function does not return on any code path. +

    + + #include <cstdlib> +ย  [[noreturn]] void f(int i) { if (i > 0) throw "Received positive input"; std::exit(0); -} +} +
    -

    Returning from a function marked [[noreturn]] results in undefined behavior that might be exploited to cause data-integrity violations.

    +

    + Returning from a function marked + + [[noreturn]] + + results in + + undefined behavior + + that might be + + exploited + + to cause data-integrity violations. +

    Subclause 3.6.1, "Main Function" Subclause 6.6.3, "The - return + + return + Statement" Subclause 15.3, "Handling an Exception"
    @@ -66,10 +135,14 @@ Low @@ -102,7 +175,9 @@ 20.10 @@ -133,27 +210,13 @@ 3.9 - - - - - - @@ -179,7 +244,11 @@ 2021.4 @@ -194,7 +263,9 @@ 2021.2 @@ -230,7 +303,9 @@ 20.10 @@ -255,7 +334,17 @@
    - P2 + + P2 + - L3 + + L3 +
    - invalid-noreturn + + invalid-noreturn + Fully checked @@ -118,7 +193,9 @@ 7.2.0 - CertC++-MSC53 + + CertC++-MSC53 + - -Winvalid-noreturn + + -Winvalid-noreturn +
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.RFNR - - Return from noreturn -
    @@ -164,7 +227,9 @@ 2021.2 - C++2886 + + C++2886 + - CERT.MSC.NORETURN_FUNC_RETURNS + + + CERT.MSC.NORETURN_FUNC_RETURNS + + - CERT_CPP-MSC53-a + + CERT_CPP-MSC53-a + Never return from functions that should not return @@ -216,7 +287,9 @@ Checks for - [[noreturn]] + + [[noreturn]] + functions returning to caller (rule fully covered)
    - invalid-noreturn + + invalid-noreturn + Fully checked @@ -246,7 +321,11 @@ 4.10 - S935 + + + S935 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -270,7 +359,9 @@ diff --git a/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction-standard.qhelp b/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction-standard.qhelp index b6682a3aba..3505b13a02 100644 --- a/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction-standard.qhelp +++ b/cpp/cert/src/rules/MSC54-CPP/SignalHandlerMustBeAPlainOldFunction-standard.qhelp @@ -1,27 +1,107 @@
    -

    The C++14 Standard, [support.runtime], paragraph 10 [ISO/IEC 14882-2014], states the following:

    +

    + The C++14 Standard, [support.runtime], paragraph 10 + [ + + ISO/IEC 14882-2014 + + ] + , states the following: +

    -

    The common subset of the C and C++ languages consists of all declarations, definitions, and expressions that may appear in a well-formed C++ program and also in a conforming C program. A POF (โ€œplain old functionโ€) is a function that uses only features from this common subset, and that does not directly or indirectly use any function that is not a POF, except that it may use plain lock-free atomic operations. A plain lock-free atomic operation is an invocation of a function f from Clause 29, such that f is not a member function, and either f is the function atomic_is_lock_free, or for every atomic argument A passed to f, atomic_is_lock_free(A) yields true. All signal handlers shall have C linkage. The behavior of any function other than a POF used as a signal handler in a C++ program is implementation-defined.228

    +

    + The common subset of the C and C++ languages consists of all declarations, definitions, and expressionsย that may appear in a well-formed C++ program and also in a conforming C program. A POF (โ€œplain oldย functionโ€) is a function that uses only features from this common subset, and that does not directly orย indirectly use any function that is not a POF, except that it may use plain lock-free atomic operations. Aย plain lock-free atomic operation is an invocation of a function f from Clause 29, such that f is not a memberย function, and either f is the function atomic_is_lock_free, or for every atomic argument Aย passed toย f, atomic_is_lock_free(A)ย yields true. All signal handlers shall have C linkage. The behavior of anyย function other than a POF used as a signal handler in a C++ program is implementation-defined.228 +

    -

    Footnote 228 states the following:

    +

    + Footnote 228 states the following: +

    -

    In particular, a signal handler using exception handling is very likely to have problems. Also, invoking std::exit may cause destruction of objects, including those of the standard library implementation, which, in general, yields undefined behavior in a signal handler.

    +

    + In particular, a signal handler using exception handling is very likely to have problems. Also, invoking + + std::exit + + may causeย destruction of objects, including those of the standard library implementation, which, in general, yields undefined behavior inย a signal handler. +

    -

    If your signal handler is not a plain old function, then the behavior of a call to it in response to a signal is implementation-defined, at best, and is likely to result in undefined behavior. All signal handlers must meet the definition of a plain old function. In addition to the restrictions placed on signal handlers in a C program, this definition also prohibits the use of features that exist in C++ but not in C (such as non-POD [nonโ€“plain old data] objects and exceptions). This includes indirect use of such features through function calls.

    -

    In C++17, the wording has changed and relaxed some of the constraints on signal handlers. Section [support.signal], paragraph 3 says:

    +

    + If your signal handler is not a plain old function, then the behavior of a call to it in response to a signal is + + implementation-defined + + , at best, and is likely to result in + + undefined behavior + + . All signal handlers must meet the definition of a plain old function. In addition to the restrictions placed on signal handlers in a C program,ย this definition also prohibits the use of features that exist in C++ but not in C (such as non-POD [nonโ€“plain old data] objects and exceptions). This includes indirect use of such features through function calls. +

    +

    + In C++17, the wording has changed and relaxed some of the constraints on signal handlers. Section [support.signal], paragraph 3 says: +

    -

    An evaluation is signal-safe unless it includes one of the following:

    -

    โ€” a call to any standard library function, except for plain lock-free atomic operations and functions explicitly identified as signal-safe. [ Note: This implicitly excludes the use of new and delete expressions that rely on a library-provided memory allocator. โ€” end note ]โ€” an access to an object with thread storage duration;โ€” a dynamic_cast expression;โ€” throwing of an exception;โ€” control entering a try-block or function-try-block;โ€” initialization of a variable with static storage duration requiring dynamic initialization (6.6.3, 9.7)220; orโ€” waiting for the completion of the initialization of a variable with static storage duration (9.7).

    -

    A signal handler invocation has undefined behavior if it includes an evaluation that is not signal-safe.

    +

    + An evaluation is + signal-safe + unless it includes one of the following: +

    +

    + โ€” + a call to any standard library function, except for plain lock-free atomic operations and functions explicitly identified as signal-safe. [ + Note: + This implicitly excludes the use of + new + and + delete + expressions that rely on a library-provided memory allocator. + โ€” end note + ] + โ€” an access to an object with thread storage duration; + โ€” a + dynamic_cast + expression; + โ€” throwing of an exception; + โ€” control entering a + try-block + or + function-try-block + ; + โ€” initialization of a variable with static storage duration requiring dynamic initialization ( + 6.6.3 + , + 9.7 + ) + 220 + ; or + โ€” waiting for the completion of the initialization of a variable with static storage duration ( + 9.7 + ). +

    +

    + A signal handler invocation has undefined behavior if it includes an evaluation that is not signal-safe. +

    -

    Signal handlers in code that will be executed on C++17-compliant platforms must be signal-safe.

    +

    + Signal handlers in code that will be executed on C++17-compliant platforms must be signal-safe. +

    -

    In this noncompliant code example, the signal handler is declared as a static function. However, since all signal handler functions must have C language linkage, and C++ is the default language linkage for functions in C++, calling the signal handler results in undefined behavior.

    - #include <csignal> - +

    + In this noncompliant code example, the signal handler is declared as a + + static + + function. However, since all signal handler functions must have C language linkage, and C++ is the default language linkage for functions in C++, calling the signal handler results in + + undefined behavior + + . +

    + + #include <csignal> +ย  static void sig_handler(int sig) { // Implementation details elided. } @@ -30,11 +110,19 @@ void install_signal_handler() { if (SIG_ERR == std::signal(SIGTERM, sig_handler)) { // Handle error } -} +} +
    -

    This compliant solution defines sig_handler() as having C language linkage. As a consequence of declaring the signal handler with C language linkage, the signal handler will have external linkage rather than internal linkage.

    - #include <csignal> +

    + This compliant solution defines + + sig_handler() + + as having C language linkage. As a consequence of declaring the signal handler with C language linkage, the signal handler will have external linkage rather than internal linkage. +

    + + #include <csignal> extern "C" void sig_handler(int sig) { // Implementation details elided. @@ -44,11 +132,27 @@ void install_signal_handler() { if (SIG_ERR == std::signal(SIGTERM, sig_handler)) { // Handle error } -} +} +
    -

    In this noncompliant code example, a signal handler calls a function that allows exceptions, and it attempts to handle any exceptions thrown. Because exceptions are not part of the common subset of C and C++ features, this example results in implementation-defined behavior. However, it is unlikely that the implementation's behavior will be suitable. For instance, on a stack-based architecture where a signal is generated asynchronously (instead of as a result of a call to std:abort() or std::raise()), it is possible that the stack frame is not properly initialized, causing stack tracing to be unreliable and preventing the exception from being caught properly.

    - #include <csignal> +

    + In this noncompliant code example, a signal handler calls a function that allows exceptions, and it attempts to handle any exceptions thrown. Because exceptions are not part of the common subset of C and C++ features, this example results in + + implementation-defined behavior + + . However, it is unlikely that the implementation's behavior will be suitable. For instance, on a stack-based architecture where a signal is generated asynchronously (instead of as a result of a call to + + std:abort() + + or + + std::raise() + + ), it is possible that the stack frame is not properly initialized, causing stack tracing to be unreliable and preventing the exception from being caught properly. +

    + + #include <csignal> static void g() noexcept(false); @@ -59,16 +163,56 @@ extern "C" void sig_handler(int sig) { // Handle error } } - +ย  void install_signal_handler() { if (SIG_ERR == std::signal(SIGTERM, sig_handler)) { // Handle error } -} +} +
    -

    There is no compliant solution whereby g() can be called from the signal handler because it allows exceptions. Even if g() were implemented such that it handled all exceptions and was marked noexcept(true), it would still be noncompliant to call g() from a signal handler because g() would still use a feature that is not a part of the common subset of C and C++ features allowed by a signal handler. Therefore, this compliant solution removes the call to g() from the signal handler and instead polls a variable of type volatile sig_atomic_t periodically; if the variable is set to 1 in the signal handler, then g() is called to respond to the signal.

    - #include <csignal> +

    + There is no compliant solution whereby + + g() + + can be called from the signal handler because it allows exceptions. Even if + + g() + + were implemented such that it handled all exceptions and was marked + + noexcept(true) + + , it would still be noncompliant to call + + g() + + from a signal handler because + + g() + + would still use a feature that is not a part of the common subset of C and C++ features allowed by a signal handler. Therefore, this compliant solution removes the call to + + g() + + from the signal handler and instead polls a variable of type + + volatile sig_atomic_t + + periodically; if the variable is set to + + 1 + + in the signal handler, then + + g() + + is called to respond to the signal. +

    + + #include <csignal> volatile sig_atomic_t signal_flag = 0; static void g() noexcept(false); @@ -82,7 +226,7 @@ void install_signal_handler() { // Handle error } } - +ย  // Called periodically to poll the signal flag. void poll_signal_flag() { if (signal_flag == 1) { @@ -93,10 +237,25 @@ void poll_signal_flag() { // Handle error } } -} +} +
    -

    Failing to use a plain old function as a signal handler can result in implementation-defined behavior as well as undefined behavior. Given the number of features that exist in C++ that do not also exist in C, the consequences that arise from failure to comply with this rule can range from benign (harmless) behavior to abnormal program termination, or even arbitrary code execution.

    +

    + Failing to use a plain old function as a signal handler can result in + + implementation-defined behavior + + as well as + + undefined behavior + + . Given the number of features that exist in C++ that do not also exist in C, the consequences that arise from failure to comply with this rule can range from benign (harmless) behavior to + + abnormal program termination + + , or even arbitrary code execution. +

    Subclause 7.6.3, " - noreturn + + noreturn + Attribute"
    @@ -133,10 +292,14 @@ void poll_signal_flag() { High @@ -169,7 +332,9 @@ void poll_signal_flag() { 2021.2 @@ -184,7 +349,11 @@ void poll_signal_flag() { 2021.4 @@ -199,7 +368,9 @@ void poll_signal_flag() { 2021.2 @@ -224,7 +397,17 @@ void poll_signal_flag() {
    - P6 + + P6 + - L2 + + L2 +
    - C++2888 + + C++2888 + - CERT.MSC.SIG_HANDLER.POF + + + CERT.MSC.SIG_HANDLER.POF + + - CERT_CPP-MSC54-a + + CERT_CPP-MSC54-a + Properly define signal handlers @@ -215,7 +386,9 @@ void poll_signal_flag() { 4.4 - 2888 + + 2888 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors-standard.qhelp b/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors-standard.qhelp index cc8413bcbf..316091ecec 100644 --- a/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors-standard.qhelp +++ b/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors-standard.qhelp @@ -1,19 +1,72 @@
    -

    Virtual functions allow for the choice of member function calls to be determined at run time based on the dynamic type of the object that the member function is being called on. This convention supports object-oriented programming practices commonly associated with object inheritance and function overriding. When calling a nonvirtual member function or when using a class member access expression to denote a call, the specified function is called. Otherwise, a virtual function call is made to the final overrider in the dynamic type of the object expression.

    -

    However, during the construction and destruction of an object, the rules for virtual method dispatch on that object are restricted. The C++ Standard, [class.cdtor], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + Virtual functions allow for the choice of member function calls to be determined at run time based on the dynamic type of the object that the member function is being called on. This convention supports object-oriented programming practices commonly associated with object inheritance and function overriding. When calling a nonvirtual member function or when using a class member access expression to denote a call, the specified function is called. Otherwise, a virtual function call is made to the final overrider in the dynamic type of the object expression. +

    +

    + However, during the construction and destruction of an object, the rules for virtual method dispatch on that object are restricted. The C++ Standard, [class.cdtor], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , states the following: +

    -

    Member functions, including virtual functions, can be called during construction or destruction. When a virtual function is called directly or indirectly from a constructor or from a destructor, including during the construction or destruction of the classโ€™s non-static data members, and the object to which the call applies is the object (call it x) under construction or destruction, the function called is the final overrider in the constructorโ€™s or destructorโ€™s class and not one overriding it in a more-derived class. If the virtual function call uses an explicit class member access and the object expression refers to the complete object of x or one of that objectโ€™s base class subobjects but not x or one of its base class subobjects, the behavior is undefined.

    +

    + Member functions, including virtual functions, can be called during construction or destruction.ย When a virtual function is called directly or indirectly from a constructor or from a destructor, includingย during the construction or destruction of the classโ€™s non-static data members, and the object to which theย call applies is the object (call it + + x + + ) under construction or destruction, the function called is the final overriderย in the constructorโ€™s or destructorโ€™s class and not one overriding it in a more-derived class. If the virtualย function call uses an explicit class member accessย and the object expression refers to the completeย object of + + x + + or one of that objectโ€™s base class subobjects but not + + x + + or one of its base class subobjects, theย behavior is undefined. +

    -

    Do not directly or indirectly invoke a virtual function from a constructor or destructor that attempts to call into the object under construction or destruction. Because the order of construction starts with base classes and moves to more derived classes, attempting to call a derived class function from a base class under construction is dangerous. The derived class has not had the opportunity to initialize its resources, which is why calling a virtual function from a constructor does not result in a call to a function in a more derived class. Similarly, an object is destroyed in reverse order from construction, so attempting to call a function in a more derived class from a destructor may access resources that have already been released.

    +

    + Do not directly or indirectly invoke a virtual function from a constructor or destructor that attempts to call into the object under construction or destruction. Because the order of construction starts with base classes and moves to more derived classes, attempting to call a derived class function from a base class under construction is dangerous. The derived class has not had the opportunity to initialize its resources, which is whyย calling a virtual function from a constructor does not result in a call to a function in a more derived class. Similarly, an object is destroyed in reverse order from construction, so attempting to call a function in a more derived class from a destructor may access resources that have already been released. +

    -

    In this noncompliant code example, the base class attempts to seize and release an object's resources through calls to virtual functions from the constructor and destructor. However, the B::B() constructor calls B::seize() rather than D::seize(). Likewise, the B::~B() destructor calls B::release() rather than D::release().

    - struct B { +

    + In this noncompliant code example, the base class attempts to seize and release an object's resources through calls to virtual functions from the constructor and destructor. However, the + + B::B() + + constructor calls + + B::seize() + + rather than + + D::seize() + + . Likewise, the + + B::~B() + + destructor calls + + B::release() + + rather than + + D::release() + + . +

    + + struct B { B() { seize(); } virtual ~B() { release(); } - +ย  protected: virtual void seize(); virtual void release(); @@ -21,24 +74,73 @@ protected: struct D : B { virtual ~D() = default; - +ย  protected: void seize() override { B::seize(); // Get derived resources... } - +ย  void release() override { // Release derived resources... B::release(); } }; - -

    The result of running this code is that no derived class resources will be seized or released during the initialization and destruction of object of type D. At the time of the call to seize() from B::B(), the D constructor has not been entered, and the behavior of the under-construction object will be to invoke B::seize() rather than D::seize(). A similar situation occurs for the call to release() in the base class destructor. If the functions seize() and release() were declared to be pure virtual functions, the result would be undefined behavior.

    +
    +

    + The result of running this code is that no derived class resources will be seized or released during the initialization and destruction of object of type + + D + + . At the time of the call to + + seize() + + from + + B::B() + + , the + + D + + constructor has not been entered, and the behavior of the under-construction object will be to invoke + + B::seize() + + rather than + + D::seize() + + . A similar situation occurs for the call to + + release() + + in the base class destructor. If the functions + + seize() + + and + + release() + + were declared to be pure virtual functions, the result would be + + undefined behavior + + . +

    -

    In this compliant solution, the constructors and destructors call a nonvirtual, private member function (suffixed with mine) instead of calling a virtual function. The result is that each class is responsible for seizing and releasing its own resources.

    - class B { +

    + In this compliant solution, the constructors and destructors call a nonvirtual, private member function (suffixed with + + mine + + ) instead of calling a virtual function. The result is that each class is responsible for seizing and releasing its own resources. +

    + + class B { void seize_mine(); void release_mine(); @@ -69,43 +171,81 @@ protected: release_mine(); B::release(); } -}; +}; +
    -

    OOP50-CPP-EX1: Because valid use cases exist that involve calling (non-pure) virtual functions from the constructor of a class, it is permissible to call the virtual function with an explicitly qualified ID. The qualified ID signifies to code maintainers that the expected behavior is for the class under construction or destruction to be the final overrider for the function call.

    - struct A { +

    + + OOP50-CPP-EX1: + + Because valid use cases exist that involve calling (non-pure) virtual functions from the constructor of a class, it is permissible to call the virtual function with an explicitly qualified ID. The qualified ID signifies to code maintainers that the expected behavior is for the class under construction or destruction to be the final overrider for the function call. +

    + + struct A { A() { // f(); // WRONG! A::f(); // Okay } virtual void f(); }; - -

    OOP50-CPP-EX2: It is permissible to call a virtual function that has the final virt-specifier from a constructor or destructor, as in this example.

    - struct A { + +

    + + OOP50-CPP-EX2: + + It is permissible to call a virtual function that has the + + final + + + virt-specifier + + from a constructor or destructor, as in this example. +

    + + struct A { A(); virtual void f(); }; - +ย  struct B : A { B() : A() { f(); // Okay } void f() override final; -}; -

    Similarly, it is permissible to call a virtual function from a constructor or destructor of a class that has the final class-virt-specifier, as in this example.

    - struct A { +}; + +

    + Similarly, it is permissible to call a virtual function from a constructor or destructor of a class that has the + + final + + + class-virt-specifier + + , as in this example. +

    + + struct A { A(); virtual void f(); }; - +ย  struct B final : A { B() : A() { f(); // Okay } void f() override; -}; -

    In either case, f() must be the final overrider, guaranteeing consistent behavior of the function being called.

    +}; +
    +

    + In either case, + + f() + + must be the final overrider, guaranteeing consistent behavior of the function being called. +

    @@ -144,10 +284,14 @@ struct B final : A { Medium @@ -180,7 +324,10 @@ struct B final : A { 20.10 @@ -211,29 +360,15 @@ struct B final : A { 3.9 - - - - - - @@ -246,7 +381,9 @@ struct B final : A { 2021.2 @@ -260,7 +397,9 @@ struct B final : A { @@ -316,7 +463,11 @@ struct B final : A { 4.4 @@ -328,10 +479,14 @@ struct B final : A { @@ -346,7 +501,9 @@ struct B final : A { 20.10 @@ -371,7 +532,17 @@ struct B final : A {
    - P2 + + P2 + - L3 + + L3 +
    - virtual-call-in-constructorinvalid_function_pointer + + virtual-call-in-constructor + invalid_function_pointer + Fully checked @@ -196,7 +343,9 @@ struct B final : A { 7.2.0 - CertC++-OOP50 + + CertC++-OOP50 + - clang-analyzer-alpha.cplusplus.VirtualCall + + clang-analyzer-alpha.cplusplus.VirtualCall + Checked by - clang-tidy -
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.VCALL_IN_CTOR - LANG.STRUCT.VCALL_IN_DTOR - - Virtual Call in Constructor - Virtual Call in Destructor + + clang-tidy +
    - C++4260, C++4261, C++4273, C++4274, C++4275, C++4276, C++4277, C++4278, C++4279, C++4280, C++4281, C++4282 + + C++4260, C++4261, C++4273, C++4274, C++4275, C++4276, C++4277, C++4278, C++4279, C++4280, C++4281, C++4282 + - 467 S, 92 D + + 467 S, 92 D + Fully implemented @@ -276,10 +415,18 @@ struct B final : A { 2021.2 - CERT_CPP-OOP50-a - CERT_CPP-OOP50-b - CERT_CPP-OOP50-c - CERT_CPP-OOP50-d + + CERT_CPP-OOP50-a + + + CERT_CPP-OOP50-b + + + CERT_CPP-OOP50-c + + + CERT_CPP-OOP50-d + Avoid calling virtual functions from constructors @@ -303,7 +450,7 @@ struct B final : A { - Checks for virtual function call from constructors and destructors (rule fully covered) + Checks forย virtual function call from constructors and destructors (rule fully covered)
    - 4260, 4261, 4273, 4274,4275, 4276, 4277, 4278,4279, 4280, 4281, 4282 + + 4260, 4261, 4273, 4274, + 4275, 4276, 4277, 4278, + 4279, 4280, 4281, 4282 + - 7.17 + 7.16 - V1053 + + + V1053 + + - virtual-call-in-constructor + + virtual-call-in-constructor + Fully checked @@ -362,7 +519,11 @@ struct B final : A { 4.10 - S1699 + + + S1699 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql b/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql index 4a3aab6e39..5cbcee6be9 100644 --- a/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql +++ b/cpp/cert/src/rules/OOP50-CPP/DoNotInvokeVirtualFunctionsFromConstructorsOrDestructors.ql @@ -68,7 +68,8 @@ predicate indirectlyCallsVirtualFunction(MemberFunction caller, Function target, from FunctionCall call, string explanation, Function virtFunction, Function overridingFunction where -not isExcluded(virtFunction, InheritancePackage::doNotInvokeVirtualFunctionsFromConstructorsOrDestructorsQuery()) and + not isExcluded(virtFunction, + InheritancePackage::doNotInvokeVirtualFunctionsFromConstructorsOrDestructorsQuery()) and ( // for calls within a constructor or destructor call.getEnclosingFunction() instanceof Constructor or diff --git a/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects-standard.qhelp b/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects-standard.qhelp index bcbb66c2f0..2b0fab854a 100644 --- a/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects-standard.qhelp +++ b/cpp/cert/src/rules/OOP51-CPP/DoNotSliceDerivedObjects-standard.qhelp @@ -1,12 +1,43 @@
    -

    An object deriving from a base class typically contains additional member variables that extend the base class. When by-value assigning or copying an object of the derived type to an object of the base type, those additional member variables are not copied because the base class contains insufficient space in which to store them. This action is commonly called slicing the object because the additional members are "sliced off" the resulting object.

    -

    Do not initialize an object of base class type with an object of derived class type, except through references, pointers, or pointer-like abstractions (such as std::unique_ptr, or std::shared_ptr).

    +

    + An object deriving from a base class typically contains additional member variables that extend the base class. When by-valueย assigning or copying an object of the derived type to an object of the base type, those additional member variables are not copied because the base class contains insufficient space in which to store them. This action is commonly called + + slicing + + the object because the additional members are "sliced off" the resulting object. +

    +

    + Do not initialize an object of base class type with an object of derived class type, except through references, pointers, or pointer-like abstractions (such as + + std::unique_ptr, or std::shared_ptr + + ). +

    -

    In this noncompliant code example, an object of the derived Manager type is passed by value to a function accepting a base Employee type. Consequently, the Manager objects are sliced, resulting in information loss and unexpected behavior when the print() function is called.

    - #include <iostream> +

    + In this noncompliant code example, an object of the derived + + Manager + + type is passed by value to a function accepting a base + + Employee + + type. Consequently, the + + Manager + + objects are sliced, resulting in information loss and unexpected behavior when the + + print() + + function is called. +

    + + #include <iostream> #include <string> class Employee { @@ -53,14 +84,49 @@ int main() { f(typist); f(designer); } - -

    When f() is called with the designer argument, the formal parameter in f() is sliced and information is lost. When the object e is printed, Employee::print() is called instead of Manager::print(), resulting in the following output:

    - Employee: Jane Doe +
    +

    + When + + f() + + is called with the + + designer + + argument, the formal parameter in + + f() + + is sliced and information is lost. When the object + + e + + is printed, + + Employee::print() + + is called instead of + + Manager::print() + + , resulting in the following output: +

    + + Employee: Jane Doe +
    -

    Using the same class definitions as the noncompliant code example, this compliant solution modifies the definition of f() to require raw pointers to the object, removing the slicing problem.

    - // Remainder of code unchanged... - +

    + Using the same class definitions as the noncompliant code example, this compliant solution modifies the definition of + + f() + + to require raw pointers to the object, removing the slicing problem. +

    + + // Remainder of code unchanged... +ย  void f(const Employee *e) { if (e) { std::cout << *e; @@ -76,17 +142,36 @@ int main() { f(&typist); f(&designer); } - -

    This compliant solution also complies with EXP34-C. Do not dereference null pointers in the implementation of f(). With this definition, the program correctly outputs the following.

    - Employee: Joe Smith + +

    + This compliant solution also complies with + + EXP34-C. Do not dereference null pointers + + in the implementation of + + f() + + . With this definition, the program correctly outputs the following. +

    + + Employee: Joe Smith Employee: Bill Jones Manager: Jane Doe Assistant: - Employee: Bill Jones + Employee: Bill Jones +
    -

    An improved compliant solution, which does not require guarding against null pointers within f(), uses references instead of pointers.

    - // ... Remainder of code unchanged ... +

    + An improved compliant solution, which does not require guarding against null pointers within + + f() + + , uses references instead of pointers. +

    + + // ... Remainder of code unchanged ... void f(const Employee &e) { std::cout << e; @@ -100,11 +185,43 @@ int main() { f(coder); f(typist); f(designer); -} +} +
    -

    Both previous compliant solutions depend on consumers of the Employee and Manager types to be declared in a compliant manner with the expected usage of the class hierarchy. This compliant solution ensures that consumers are unable to accidentally slice objects by removing the ability to copy-initialize an object that derives from Noncopyable. If copy-initialization is attempted, as in the original definition of f(), the program is ill-formed and a diagnostic will be emitted. However, such a solution also restricts the Manager object from attempting to copy-initialize its Employee object, which subtly changes the semantics of the class hierarchy.

    - #include <iostream> +

    + Both previous compliant solutions depend on consumers of the + + Employee + + and + + Manager + + types to be declared in a compliant manner with the expected usage of the class hierarchy. This compliant solution ensures that consumers are unable to accidentally slice objects by removing the ability to copy-initialize an object that derives from + + Noncopyable + + . If copy-initialization is attempted, as in the original definition of + + f() + + , the program is + + ill-formed + + and a diagnostic will be emitted. However, such a solution also restricts the + + Manager + + object from attempting to copy-initialize its + + Employee + + object, which subtly changes the semantics of the class hierarchy. +

    + + #include <iostream> #include <string> class Noncopyable { @@ -147,7 +264,7 @@ public: Manager(const std::string &name, const Employee &assistant) : Employee(name), assistant(assistant) {} const Employee &get_assistant() const { return assistant; } }; - +ย  // If f() were declared as accepting an Employee, the program would be // ill-formed because Employee cannot be copy-initialized. void f(const Employee &e) { @@ -162,14 +279,38 @@ int main() { f(coder); f(typist); f(designer); -} +} +
    -

    This noncompliant code example uses the same class definitions of Employee and Manager as in the previous noncompliant code example and attempts to store Employee objects in a std::vector. However, because std::vector requires a homogeneous list of elements, slicing occurs.

    - #include <iostream> +

    + This noncompliant code example uses the same class definitions of + + Employee + + and + + Manager + + as in the previous noncompliant code example and attempts to store + + Employee + + objects in a + + std::vector + + . However, because + + std::vector + + requires a homogeneous list of elements, slicing occurs. +

    + + #include <iostream> #include <string> #include <vector> - +ย  void f(const std::vector<Employee> &v) { for (const auto &e : v) { std::cout << e; @@ -180,11 +321,19 @@ int main() { Employee typist("Joe Smith"); std::vector<Employee> v{typist, Employee("Bill Jones"), Manager("Jane Doe", typist)}; f(v); -} +} +
    -

    This compliant solution uses a vector of std::unique_ptr objects, which eliminates the slicing problem.

    - #include <iostream> +

    + This compliant solution uses a vector of + + std::unique_ptr + + objects,ย which eliminates the slicing problem. +

    + + #include <iostream> #include <memory> #include <string> #include <vector> @@ -203,10 +352,17 @@ int main() { v.emplace_back(new Manager("Jane Doe", *v.front())); f(v); -} +} +
    -

    Slicing results in information loss, which could lead to abnormal program execution or denial-of-service attacks.

    +

    + Slicing results in information loss, which could lead to abnormal program execution or + + denial-of-service attacks + + . +

    @@ -243,10 +399,14 @@ int main() { Medium @@ -269,22 +429,6 @@ int main() { Description - - - - - - @@ -310,7 +456,9 @@ int main() { 2021.2 @@ -356,10 +506,14 @@ int main() { @@ -368,7 +522,17 @@ int main() {
    - P4 + + P4 + - L3 + + L3 +
    - - CodeSonar - - - 6.2p0 - - LANG.CAST.OBJSLICE - - Object Slicing -
    @@ -295,7 +439,9 @@ int main() { 2021.2 - C++3072 + + C++3072 + - CERT_CPP-OOP51-a + + CERT_CPP-OOP51-a + Avoid slicing function arguments / return value @@ -344,7 +492,9 @@ int main() { 4.4 - 3072 + + 3072 + - 7.17 + 7.16 - V1054 + + + V1054 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor-standard.qhelp b/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor-standard.qhelp index 3c65030ab1..bad61be999 100644 --- a/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor-standard.qhelp +++ b/cpp/cert/src/rules/OOP52-CPP/DoNotDeleteAPolymorphicObjectWithoutAVirtualDestructor-standard.qhelp @@ -1,48 +1,160 @@
    -

    The C++ Standard, [expr.delete], paragraph 3 [ISO/IEC 14882-2014], states the following:

    +

    + The C++ Standard,ย [expr.delete], paragraph 3 + [ + + ISO/IEC 14882-2014 + + ], + states the following: +

    -

    In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

    +

    + In the first alternative ( + + delete object + + ), if the static type of the object to be deleted is different from itsย dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and theย static type shall have a virtual destructor or the behavior is undefined. In the second alternative ( + + deleteย array + + ) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined. +

    -

    Do not delete an object of derived class type through a pointer to its base class type that has a non-virtual destructor. Instead, the base class should be defined with a virtual destructor. Deleting an object through a pointer to a type without a virtual destructor results in undefined behavior.

    +

    + Do not delete an object of derived class type through a pointer to its base class type that has a non- + + virtual + + destructor.ย Instead, the base class should be defined with a + + virtual + + destructor. Deleting an object through a pointer to a type without a + + virtual + + destructorย results in + + undefined behavior + + . +

    -

    In this noncompliant example, b is a polymorphic pointer type whose static type is Base * and whose dynamic type is Derived *. When b is deleted, it results in undefined behavior because Base does not have a virtual destructor. The C++ Standard, [class.dtor], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +

    + In this noncompliant example, + + b + + is a polymorphic pointer type whose static type is + + Base * + + and whose dynamic type is + + Derived * + + . When + + b + + is deleted, it results in + + undefined behavior + + because + + Base + + does not have a + + virtual + + destructor. The C++ Standard, [class.dtor], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ], states the following + : +

    -

    If a class has no user-declared destructor, a destructor is implicitly declared as defaulted. An implicitly declared destructor is an inline public member of its class.

    +

    + If a class has no user-declared destructor, a destructor is implicitly declared as defaulted. An implicitly declared destructor is an + + inline public + + member of its class. +

    -

    The implicitly declared destructor is not declared as virtual even in the presence of other virtual functions.

    - struct Base { +

    + The implicitly declared destructor is not declared as + + virtual + + even in the presence of other + + virtual + + functions. +

    + + struct Base { virtual void f(); }; - +ย  struct Derived : Base {}; - +ย  void f() { Base *b = new Derived(); // ... delete b; } - +
    -

    In this noncompliant example, the explicit pointer operations have been replaced with a smart pointer object, demonstrating that smart pointers suffer from the same problem as other pointers. Because the default deleter for std::unique_ptr calls delete on the internal pointer value, the resulting behavior is identical to the previous noncompliant example.

    - #include <memory> - +

    + In this noncompliant example, the explicit pointer operations have been replaced with a smart pointer object, demonstrating that smart pointers suffer from the same problem as other pointers. Because the default deleter for + + std::unique_ptr + + calls + + delete + + on the internal pointer value, the resulting behavior is identical to the previous noncompliant example. +

    + + #include <memory> +ย  struct Base { virtual void f(); }; - +ย  struct Derived : Base {}; - +ย  void f() { std::unique_ptr<Base> b = std::make_unique<Derived()>(); -} +} +
    -

    In this compliant solution, the destructor for Base has an explicitly declared virtual destructor, ensuring that the polymorphic delete operation results in well-defined behavior.

    - struct Base { +

    + In this compliant solution, the destructor for + + Base + + has an explicitly declared + + virtual + + destructor, ensuring that the polymorphic delete operation results in well-defined behavior. +

    + + struct Base { virtual ~Base() = default; virtual void f(); }; @@ -53,11 +165,18 @@ void f() { Base *b = new Derived(); // ... delete b; -} +} +
    -

    OOP52-CPP:EX0: Deleting a polymorphic object without a virtual destructor is permitted if the object is referenced by a pointer to its class, rather than via a pointer to a class it inherits from.

    - class Base { +

    + + OOP52-CPP:EX0 + + : Deleting a polymorphic object without a virtual destructor is permitted if the object is referenced by a pointer to its class, rather than via a pointer to a class it inherits from. +

    + + class Base { public: // ... virtual void AddRef() = 0; @@ -71,10 +190,39 @@ public: virtual void Destroy() { delete this; } private: ~Derived() {} -}; -

    Note that if Derived were not marked as final, then delete this could actually reference a subclass of Derived, violating this rule.

    -

    OOP52-CPP:EX1: Deleting a polymorphic object without a virtual destructor is permitted if its base class has a destroying operator delete that will figure out the correct derived class's destructor to call by other means.

    - #include <new> +}; + +

    + Note that if + + Derived + + were not marked as + + final + + , then + + delete this + + could actually reference a subclass of + + Derived + + , violating this rule. +

    +

    + + OOP52-CPP:EX1 + + : Deleting a polymorphic object without a virtual destructor is permitted if its base class has a destroying + + operator delete + + that will figure out the correct derived class's destructor to call by other means. +

    + + #include <new> class Base { const int whichDerived; @@ -113,10 +261,25 @@ void f() { Base *b = new Derived1(); // ... delete b; -} +} +
    -

    Attempting to destruct a polymorphic object that does not have a virtual destructor declared results in undefined behavior. In practice, potential consequences include abnormal program termination and memory leaks.

    +

    + Attempting to destruct a polymorphic object that does not have a + + virtual + + destructor declared results in + + undefined behavior + + . In practice, potential consequences include + + abnormal program termination + + and memory leaks. +

    @@ -153,10 +316,14 @@ void f() { Low @@ -189,7 +356,9 @@ void f() { 20.10 @@ -220,25 +391,11 @@ void f() { 3.9 - - - - - - @@ -251,7 +408,9 @@ void f() { 2021.2 @@ -266,8 +425,16 @@ void f() { 2021.4 @@ -281,7 +448,9 @@ void f() { @@ -343,12 +516,20 @@ void f() { @@ -363,7 +544,9 @@ void f() { 20.10 @@ -388,7 +575,17 @@ void f() {
    - P9 + + P9 + - L2 + + L2 +
    - non-virtual-public-destructor-in-non-final-class + + non-virtual-public-destructor-in-non-final-class + Partially checked @@ -205,7 +374,9 @@ void f() { 7.2.0 - CertC++-OOP52 + + CertC++-OOP52 + - -Wdelete-non-virtual-dtor - -
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.DNVD + + -Wdelete-non-virtual-dtor + - delete with Non-Virtual Destructor
    - C++3402, C++3403, C++3404 + + C++3402, C++3403, C++3404 + - CL.MLK.VIRTUAL - CWARN.DTOR.NONVIRT.DELETE + + + CL.MLK.VIRTUAL + + + + + CWARN.DTOR.NONVIRT.DELETE + + - 303 S + + 303 S + Partially implemented @@ -297,7 +466,9 @@ void f() { 2021.2 - CERT_CPP-OOP52-a + + CERT_CPP-OOP52-a + Define a virtual destructor in classes used as base classes which have virtual functions @@ -313,7 +484,9 @@ void f() { 4.4 - 3402, 3403, 3404 + + 3402, 3403, 3404 + - 7.17 + 7.16 - V599 + + V599 + + + , - V689 + + + V689 + + - non-virtual-public-destructor-in-non-final-class + + non-virtual-public-destructor-in-non-final-class + Partially checked @@ -379,7 +562,11 @@ void f() { 4.10 - S1235 + + + S1235 + +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit-standard.qhelp b/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit-standard.qhelp index 3bb97d30f0..36643b6f59 100644 --- a/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit-standard.qhelp +++ b/cpp/cert/src/rules/OOP53-CPP/UseCanonicalOrderForMemberInit-standard.qhelp @@ -1,47 +1,134 @@
    -

    The member initializer list for a class constructor allows members to be initialized to specified values and for base class constructors to be called with specific arguments. However, the order in which initialization occurs is fixed and does not depend on the order written in the member initializer list. The C++ Standard, [class.base.init], paragraph 11 [ISO/IEC 14882-2014], states the following:

    +

    + The member initializer list for a class constructor allows members to be initialized to specified values and for base class constructors to be called with specific arguments. However, the order in which initialization occurs is fixed and does not depend on the order written in the member initializer list. The C++ Standard,ย [class.base.init], paragraph 11 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    In a non-delegating constructor, initialization proceeds in the following order:โ€” First, and only for the constructor of the most derived class, virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where โ€œleft-to-rightโ€ is the order of appearance of the base classes in the derived class base-specifier-list.โ€” Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).โ€” Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).โ€” Finally, the compound-statement of the constructor body is executed.[Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. โ€”end note]

    +

    + In a non-delegating constructor, initialization proceeds in the following order: + โ€” First, and only for the constructor of the most derived class, virtual base classes are initialized inย the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes,ย where โ€œleft-to-rightโ€ is the order of appearance of the base classes in the derived class base-specifier-list. + โ€” Then, direct base classes are initialized in declaration order as they appear in the base-specifier-listย (regardless of the order of the mem-initializers). + โ€” Then, non-static data members are initialized in the order they were declared in the class definitionย (again regardless of the order of the mem-initializers). + โ€” Finally, the compound-statement of the constructor body is executed. + [Note: The declaration order is mandated to ensure that base and member subobjects are destroyed inย the reverse order of initialization. โ€”end note] +

    -

    Consequently, the order in which member initializers appear in the member initializer list is irrelevant. The order in which members are initialized, including base class initialization, is determined by the declaration order of the class member variables or the base class specifier list. Writing member initializers other than in canonical order can result in undefined behavior, such as reading uninitialized memory.

    -

    Always write member initializers in a constructor in the canonical order: first, direct base classes in the order in which they appear in the base-specifier-list for the class, then nonstatic data members in the order in which they are declared in the class definition.

    +

    + Consequently, the order in which member initializers appear in the member initializer list is irrelevant. The order in which members are initialized, including base class initialization, is determined by the declaration order of the class member variables or the base class specifier list. Writing member initializers other than in canonical order can result in + + undefined behavior + + , such as reading uninitialized memory. +

    +

    + Always write member initializers in a constructor in the canonical order: first, direct base classes in the order in which they appear in the + + base-specifier-list + + for the class, then nonstatic data members in the order in which they are declared in the class definition. +

    -

    In this noncompliant code example, the member initializer list for C::C() attempts to initialize someVal first and then to initialize dependsOnSomeVal to a value dependent on someVal. Because the declaration order of the member variables does not match the member initializer order, attempting to read the value of someVal results in an unspecified value being stored into dependsOnSomeVal.

    - class C { +

    + In this noncompliant code example, the member initializer list for + + C::C() + + attempts to initialize + + someVal + + first and then to initialize + + dependsOnSomeVal + + to a value dependent on + + someVal + + . Because the declaration order of the member variables does not match the member initializer order, attempting to read the value of + + someVal + + results in an + + unspecified value + + being stored into + dependsOnSomeVal + . +

    + + class C { int dependsOnSomeVal; int someVal; - +ย  public: C(int val) : someVal(val), dependsOnSomeVal(someVal + 1) {} -}; +}; +
    -

    This compliant solution changes the declaration order of the class member variables so that the dependency can be ordered properly in the constructor's member initializer list.

    - class C { +

    + This compliant solution changes the declaration order of the class member variables so that the dependency can be ordered properly in the constructor's member initializer list. +

    + + class C { int someVal; int dependsOnSomeVal; - +ย  public: C(int val) : someVal(val), dependsOnSomeVal(someVal + 1) {} }; - -

    It is reasonable for initializers to depend on previously initialized values.

    +
    +

    + It is reasonable for initializers to depend on previously initialized values. +

    -

    In this noncompliant code example, the derived class, D, attempts to initialize the base class, B1, with a value obtained from the base class, B2. However, because B1 is initialized before B2 due to the declaration order in the base class specifier list, the resulting behavior is undefined.

    - class B1 { +

    + In this noncompliant code example, the derived class, + + D + + , attempts to initialize the base class, + + B1 + + , with a value obtained from the base class, + + B2 + + . However, because + + B1 + + is initialized before + + B2 + + due to the declaration order in the base class specifier list, the resulting behavior is + + undefined + + . +

    + + class B1 { int val; - +ย  public: B1(int val) : val(val) {} }; class B2 { int otherVal; - +ย  public: B2(int otherVal) : otherVal(otherVal) {} int get_other_val() const { return otherVal; } @@ -50,11 +137,15 @@ public: class D : B1, B2 { public: D(int a) : B2(a), B1(get_other_val()) {} -}; +}; +
    -

    This compliant solution initializes both base classes using the same value from the constructor's parameter list instead of relying on the initialization order of the base classes.

    - class B1 { +

    + This compliant solution initializes both base classes using the same value from the constructor's parameter list instead of relying on the initialization order of the base classes. +

    + + class B1 { int val; public: @@ -71,10 +162,16 @@ public: class D : B1, B2 { public: D(int a) : B1(a), B2(a) {} -}; +}; +
    -

    OOP53-CPP-EX0: Constructors that do not use member initializers do not violate this rule.

    +

    + + OOP53-CPP-EX0: + + Constructors that do not use member initializers do not violate this rule. +

    @@ -113,10 +210,14 @@ public: Medium @@ -149,7 +250,9 @@ public: 20.10 @@ -180,25 +285,11 @@ public: 3.9 - - - - - - @@ -211,7 +302,9 @@ public: 2021.2 @@ -226,7 +319,11 @@ public: 2021.4 @@ -240,7 +337,9 @@ public: @@ -305,7 +408,9 @@ public: 20.10 @@ -330,7 +439,17 @@ public:
    - P4 + + P4 + - L3 + + L3 +
    - initializer-list-order + + initializer-list-order + Fully checked @@ -165,7 +268,9 @@ public: 7.2.0 - CertC++-OOP53 + + CertC++-OOP53 + - -Wreorder - -
    - - CodeSonar - - - 6.2p0 - - LANG.STRUCT.INIT.OOMI + + -Wreorder + - Out of Order Member Initializers
    - C++4053 + + C++4053 + - CERT.OOP.CTOR.INIT_ORDER + + + CERT.OOP.CTOR.INIT_ORDER + + - 206 S + + 206 S + Fully implemented @@ -256,7 +355,9 @@ public: 2021.2 - CERT_CPP-OOP53-a + + CERT_CPP-OOP53-a + List members in an initialization list in the order in which they are declared @@ -290,7 +391,9 @@ public: 4.4 - 4053 + + 4053 + - initializer-list-order + + initializer-list-order + Fully checked @@ -321,7 +426,11 @@ public: 4.10 - S3229 + + + S3229 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment-standard.qhelp b/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment-standard.qhelp index a704a0a3e5..86f637e3b6 100644 --- a/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment-standard.qhelp +++ b/cpp/cert/src/rules/OOP54-CPP/GracefullyHandleSelfCopyAssignment-standard.qhelp @@ -1,54 +1,129 @@
    -

    Self-copy assignment can occur in situations of varying complexity, but essentially, all self-copy assignments entail some variation of the following.

    - #include <utility> - +

    + Self-copy assignment can occur in situations of varying complexity, but essentially, all self-copy assignments entail some variation of the following. +

    + + #include <utility> +ย  struct S { /* ... */ } - +ย  void f() { S s; s = s; // Self-copy assignment -} -

    User-provided copy operators must properly handle self-copy assignment.

    -

    The postconditions required for copy assignment are specified by the C++ Standard, [utility.arg.requirements], Table 23 [ISO/IEC 14882-2014], which states that for x = y, the value of y is unchanged. When &x == &y, this postcondition translates into the values of both x and y remaining unchanged. A naive implementation of copy assignment could destroy object-local resources in the process of copying resources from the given parameter. If the given parameter is the same object as the local object, the act of destroying object-local resources will invalidate them. The subsequent copy of those resources will be left in an indeterminate state, which violates the postcondition.

    -

    A user-provided copy assignment operator must prevent self-copy assignment from leaving the object in an indeterminate state. This can be accomplished by self-assignment tests, copy-and-swap, or other idiomatic design patterns.

    -

    The C++ Standard, [copyassignable], specifies that types must ensure that self-copy assignment leave the object in a consistent state when passed to Standard Template Library (STL) functions. Since objects of STL types are used in contexts where CopyAssignable is required, STL types are required to gracefully handle self-copy assignment.

    +} +
    +

    + User-provided copy operators must properly handle self-copy assignment. +

    +

    + The postconditions required for copy assignment are specified by the C++ Standard,ย [utility.arg.requirements], Table 23 [ + + ISO/IEC 14882-2014 + + ], which states that for + + x = y + + , the value of + + y + + is unchanged. When + + &x == &y + + , this postcondition translates into the values of both + + x + + and + + y + + remaining unchanged.ย A naive implementation of copy assignment could destroy object-local resources in the process of copying resources from the given parameter. If the given parameter is the same object as the local object, the act of destroying object-local resources will invalidate them. The subsequent copy of those resources will be left in an indeterminate state, which violates the postcondition. +

    +

    + A user-provided copy assignment operator must prevent self-copy assignment from leaving the object in an indeterminate state. This can be accomplished by self-assignment tests, copy-and-swap, or other idiomatic design patterns. +

    +

    + The C++ Standard, [copyassignable], specifies that types must ensure that self-copy assignment leave the object in a consistent state when passed to Standard Template Library (STL) functions. Since objects of STL types are used in contexts where + + CopyAssignable + + is required, STL types are required to gracefully handle self-copy assignment. +

    -

    In this noncompliant code example, the copy assignment operator does not protect against self-copy assignment. If self-copy assignment occurs, this->s1 is deleted, which results in rhs.s1 also being deleted. The invalidated memory for rhs.s1 is then passed into the copy constructor for S, which can result in dereferencing an invalid pointer.

    - #include <new> - +

    + In this noncompliant code example, the copy assignment operator does not protect against self-copy assignment. If self-copy assignment occurs, + + this->s1 + + is deleted, which results in + + rhs.s1 + + also being deleted. The invalidated memory for + + rhs.s1 + + is then passed into the copy constructor for + + S + + , which can result in dereferencing an + + invalid pointer + + . +

    + + #include <new> +ย  struct S { S(const S &) noexcept; /* ... */ }; - +ย  class T { int n; S *s1; - +ย  public: T(const T &rhs) : n(rhs.n), s1(rhs.s1 ? new S(*rhs.s1) : nullptr) {} ~T() { delete s1; } - +ย  // ... - +ย  T& operator=(const T &rhs) { n = rhs.n; delete s1; s1 = new S(*rhs.s1); return *this; } -}; +}; +
    -

    This compliant solution guards against self-copy assignment by testing whether the given parameter is the same as this. If self-copy assignment occurs, then operator= does nothing; otherwise, the copy proceeds as in the original example.

    - #include <new> +

    + This compliant solution guards against self-copy assignment by testing whether the given parameter is the same as + + this + + . If self-copy assignment occurs, then + + operator= + + does nothing; otherwise, the copy proceeds as in the original example. +

    + + #include <new> struct S { S(const S &) noexcept; /* ... */ }; class T { int n; S *s1; - +ย  public: T(const T &rhs) : n(rhs.n), s1(rhs.s1 ? new S(*rhs.s1) : nullptr) {} ~T() { delete s1; } @@ -69,12 +144,45 @@ public: return *this; } }; - -

    This solution does not provide a strong exception guarantee for the copy assignment. Specifically, if an exception is called when evaluating the new expression, this has already been modified. However, this solution does provide a basic exception guarantee because no resources are leaked and all data members contain valid values. Consequently, this code complies with ERR56-CPP. Guarantee exception safety.

    +
    +

    + This solution does not provide a + + strong exception + + guarantee for the copy assignment. Specifically, if an exception is called when evaluating the + + new + + expression, + + this + + has already been modified. However, this solution does provide a basic exception guarantee because no resources are leaked and all data members contain valid values. Consequently, this code complies with + + ERR56-CPP. Guarantee exception safety + + . +

    -

    This compliant solution avoids self-copy assignment by constructing a temporary object from rhs that is then swapped with *this. This compliant solution provides a strong exception guarantee because swap() will never be called if resource allocation results in an exception being thrown while creating the temporary object.

    - #include <new> +

    + This compliant solution avoids self-copy assignment by constructing a temporary object from + + rhs + + that is then swapped with + + *this + + . This compliant solution provides a strong exception guarantee because + + swap() + + will never be called if resource allocation results in an exception being thrown while creating the temporary object. +

    + + #include <new> #include <utility> struct S { S(const S &) noexcept; /* ... */ }; @@ -88,7 +196,7 @@ public: ~T() { delete s1; } // ... - +ย  void swap(T &rhs) noexcept { using std::swap; swap(n, rhs.n); @@ -99,11 +207,23 @@ public: rhs.swap(*this); return *this; } -}; +}; +
    -

    This compliant solution uses the same classes S and T from the previous compliant solution, but adds the following public constructor and methods:

    - T(T &&rhs) { *this = std::move(rhs); } +

    + This compliant solution uses the same classes + + S + + and + + T + + from the previous compliant solution, but adds the following public constructor and methods: +

    + + T(T &&rhs) { *this = std::move(rhs); } // ... everything except operator= .. @@ -112,13 +232,34 @@ public: swap(n, rhs.n); swap(s1, rhs.s1); return *this; - } -

    The copy assignment operator uses std::move() rather than swap() to achieve safe self-assignment and a strong exception guarantee. The move assignment operator uses a move (via the method parameter) and swap.

    -

    The move constructor is not strictly necessary, but defining a move constructor along with a move assignment operator is conventional for classes that support move operations.

    -

    Note that unlike copy assignment operators, the signature of a move assignment operator accepts a non-const reference to its object with the expectation that the moved-from object will be left in an unspecified, but valid state. Move constructors have the same difference from copy constructors.

    + } +
    +

    + The copy assignment operator uses + + std::move() + + rather than + + swap() + + to achieve safe self-assignment and a strong exception guarantee. The move assignment operator uses a move (via the method parameter) and swap. +

    +

    + The move constructor is not strictly necessary, but defining a move constructor along with a move assignment operator is conventional for classes that support move operations. +

    +

    + Note that unlike copy assignment operators, the signature of a move assignment operator accepts a non-const reference to its object with the expectation that the moved-from object will be left in an unspecified, but valid state. Move constructors have the same difference from copy constructors. +

    -

    Allowing a copy assignment operator to corrupt an object could lead to undefined behavior.

    +

    + Allowing a copy assignment operator to corrupt an object could lead to + + undefined behavior + + . +

    @@ -155,10 +296,14 @@ public: High @@ -191,7 +336,9 @@ public: 20.10 @@ -206,11 +353,15 @@ public: 9.0 (r361550) @@ -224,7 +375,9 @@ public: 2021.2 @@ -239,7 +392,11 @@ public: 2021.4 @@ -254,7 +411,9 @@ public: 2021.2 @@ -297,10 +458,26 @@ public:
    - P2 + + P2 + - L3 + + L3 +
    - dangling_pointer_use + + dangling_pointer_use + - cert-oop54-cpp + + cert-oop54-cpp + Checked by - clang-tidy + + clang-tidy + .
    - C++4072, C++4073, C++4075, C++4076 + + C++4072, C++4073, C++4075, C++4076 + - CL.SELF-ASSIGN + + + CL.SELF-ASSIGN + + - CERT_CPP-OOP54-a + + CERT_CPP-OOP54-a + Check for assignment to self in operator= @@ -288,7 +447,9 @@ public: 4.4 - 4072, 4073, 4075, 4076 + + 4072, 4073, 4075, 4076 +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a partial subset of OOP58-CPP. Copy operations must not mutate the source object when copy operations do not gracefully handle self-copy assignment, because the copy operation may mutate both the source and destination objects (due to them being the same object).

    +

    + This rule is a partial subset of + + OOP58-CPP. Copy operations must not mutate the source object + + when copy operations do not gracefully handle self-copy assignment, because the copy operation may mutate both the source and destination objects (due to them being the same object). +

    @@ -340,7 +517,9 @@ public: diff --git a/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember-standard.qhelp b/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember-standard.qhelp index 0f93c06587..e7d9026a70 100644 --- a/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember-standard.qhelp +++ b/cpp/cert/src/rules/OOP55-CPP/MemberAccessWithUninitializedStaticPointerToMember-standard.qhelp @@ -1,8 +1,27 @@
    -

    The pointer-to-member operators .* and ->* are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function f() on the object o.

    - struct S { +

    + The pointer-to-member operators + + .* + + and + + ->* + + are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function + + f() + + on the object + + o + + . +

    + + struct S { void f() {} }; @@ -12,22 +31,141 @@ void func() { o.f(); (o.*pm)(); -} -

    The call of the form o.f() uses class member access at compile time to look up the address of the function S::f() on the object o. The call of the form (o.*pm)() uses the pointer-to-member operator .* to call the function at the address specified by pm. In both cases, the object o is the implicit this object within the member function S::f().

    -

    The C++ Standard, [expr.mptr.oper], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +} +
    +

    + The call of the form + + o.f() + + uses class member access at compile time to look up the address of the function + + S::f() + + on the object + + o + + . The call of the form + + (o.*pm)() + + uses the pointer-to-member operator + + .* + + to call the function at the address specified by + + pm + + . In both cases, the object + + o + + is the implicit + + this + + object within the member function + + S::f() + + . +

    +

    + The C++ Standard, [expr.mptr.oper], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , states + the following + : +

    -

    Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic type of E1 does not contain the member to which E2 refers, the behavior is undefined.

    +

    + Abbreviating + + pm-expression.*cast-expression + + as + + E1.*E2 + + , + + E1 + + is called the + + object expression + + . If the dynamicย type of + + E1 + + does not contain the member to which + + E2 + + refers, the behavior is undefined. +

    -

    A pointer-to-member expression of the form E1->*E2 is converted to its equivalent form, (*(E1)).*E2, so use of pointer-to-member expressions of either form behave equivalently in terms of undefined behavior.

    -

    Further, the C++ Standard, [expr.mptr.oper], paragraph 6, in part, states the following:

    +

    + A pointer-to-member expression of the form + + E1->*E2 + + is converted to its equivalent form, + + (*(E1)).*E2 + + , so use of pointer-to-member expressions of either form behave equivalently in terms of + + undefined behavior + + . +

    +

    + Further, the C++ Standard, + [expr.mptr.oper], paragraph 6,ย in part, states the following: +

    -

    If the second operand is the null pointer to member value, the behavior is undefined.

    +

    + If the second operand is the null pointer to member value,ย the behavior is undefined. +

    -

    Do not use a pointer-to-member expression where the dynamic type of the first operand does not contain the member to which the second operand refers, including the use of a null pointer-to-member value as the second operand.

    +

    + Do not use a pointer-to-member expression where the dynamic type of the first operand does not contain the member to which the second operand refers, including the use of a null pointer-to-member value as the second operand. +

    -

    In this noncompliant code example, a pointer-to-member object is obtained from D::g but is then upcast to be a B::*. When called on an object whose dynamic type is D, the pointer-to-member call is well defined. However, the dynamic type of the underlying object is B, which results in undefined behavior.

    - struct B { +

    + In this noncompliant code example, a pointer-to-member object is obtained from + + D::g + + butย is thenย upcast to be a + + B::* + + . When called on an object whose dynamic type is + + D + + , the pointer-to-member call is well defined. However, the dynamic type of the underlying objectย is + + B + + , which results in + + undefined behavior + + . +

    + + struct B { virtual ~B() = default; }; @@ -38,18 +176,29 @@ struct D : B { void f() { B *b = new B; - +ย  // ... - +ย  void (B::*gptr)() = static_cast<void(B::*)()>(&D::g); (b->*gptr)(); delete b; } - +
    -

    In this compliant solution, the upcast is removed, rendering the initial code ill-formed and emphasizing the underlying problem that B::g() does not exist. This compliant solution assumes that the programmer's intention was to use the correct dynamic type for the underlying object.

    - struct B { +

    + In this compliant solution, the upcast is removed, rendering the initial code + + ill-formed + + and emphasizing the underlying problem that + + B::g() + + does not exist. This compliant solution assumes that the programmer's intention was to use the correct dynamic type for the underlying object. +

    + + struct B { virtual ~B() = default; }; @@ -60,17 +209,24 @@ struct D : B { void f() { B *b = new D; // Corrected the dynamic object type. - +ย  // ... void (D::*gptr)() = &D::g; // Moved static_cast to the next line. (static_cast<D *>(b)->*gptr)(); delete b; } - +
    -

    In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in undefined behavior.

    - struct B { +

    + In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in + + undefined behavior + + . +

    + + struct B { virtual ~B() = default; }; @@ -78,39 +234,52 @@ struct D : B { virtual ~D() = default; virtual void g() { /* ... */ } }; - +ย  static void (D::*gptr)(); // Not explicitly initialized, defaults to nullptr. void call_memptr(D *ptr) { (ptr->*gptr)(); } - +ย  void f() { D *d = new D; call_memptr(d); delete d; -} +} +
    -

    In this compliant solution, gptr is properly initialized to a valid pointer-to-member value instead of to the default value of nullptr.

    - struct B { +

    + In this compliant solution, + + gptr + + is properly initialized to a valid pointer-to-member value instead of to the default value of + + nullptr + + . +

    + + struct B { virtual ~B() = default; }; - +ย  struct D : B { virtual ~D() = default; virtual void g() { /* ... */ } }; - +ย  static void (D::*gptr)() = &D::g; // Explicitly initialized. void call_memptr(D *ptr) { (ptr->*gptr)(); } - +ย  void f() { D *d = new D; call_memptr(d); delete d; -} +} +
    Item 11, "Handle Assignment to Self in - operator= + + operator= + "
    @@ -149,10 +318,14 @@ void f() { High @@ -185,7 +358,10 @@ void f() { 20.10 @@ -200,7 +376,9 @@ void f() { 7.2.0 @@ -215,7 +393,9 @@ void f() { 2021.2 @@ -230,7 +410,11 @@ void f() { 2021.4 @@ -245,7 +429,9 @@ void f() { 2021.2 @@ -284,10 +472,28 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - overflow_upon_dereferenceinvalid_function_pointer + + overflow_upon_dereference + invalid_function_pointer + - CertC++-OOP55 + + CertC++-OOP55 + - C++2810, C++2811, C++2812, C++2813, C++2814 + + C++2810, C++2811, C++2812, C++2813, C++2814 + - CERT.OOP.PTR_MEMBER.NO_MEMBER + + + CERT.OOP.PTR_MEMBER.NO_MEMBER + + - CERT_CPP-OOP55-a + + CERT_CPP-OOP55-a + A cast shall not convert a pointer to a function to any other pointer type, including a pointer to function type @@ -275,7 +461,9 @@ void f() { 4.4 - 2810, 2811, 2812, 2813, 2814 + + 2810, 2811, 2812, 2813, 2814 +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of EXP34-C. Do not dereference null pointers.

    +

    + + This rule is a subset of + + EXP34-C. Do not dereference null pointers + + . + +

    diff --git a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember-standard.qhelp b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember-standard.qhelp index 0f93c06587..e7d9026a70 100644 --- a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember-standard.qhelp +++ b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessNonexistentMember-standard.qhelp @@ -1,8 +1,27 @@
    -

    The pointer-to-member operators .* and ->* are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function f() on the object o.

    - struct S { +

    + The pointer-to-member operators + + .* + + and + + ->* + + are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function + + f() + + on the object + + o + + . +

    + + struct S { void f() {} }; @@ -12,22 +31,141 @@ void func() { o.f(); (o.*pm)(); -} -

    The call of the form o.f() uses class member access at compile time to look up the address of the function S::f() on the object o. The call of the form (o.*pm)() uses the pointer-to-member operator .* to call the function at the address specified by pm. In both cases, the object o is the implicit this object within the member function S::f().

    -

    The C++ Standard, [expr.mptr.oper], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +} +
    +

    + The call of the form + + o.f() + + uses class member access at compile time to look up the address of the function + + S::f() + + on the object + + o + + . The call of the form + + (o.*pm)() + + uses the pointer-to-member operator + + .* + + to call the function at the address specified by + + pm + + . In both cases, the object + + o + + is the implicit + + this + + object within the member function + + S::f() + + . +

    +

    + The C++ Standard, [expr.mptr.oper], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , states + the following + : +

    -

    Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic type of E1 does not contain the member to which E2 refers, the behavior is undefined.

    +

    + Abbreviating + + pm-expression.*cast-expression + + as + + E1.*E2 + + , + + E1 + + is called the + + object expression + + . If the dynamicย type of + + E1 + + does not contain the member to which + + E2 + + refers, the behavior is undefined. +

    -

    A pointer-to-member expression of the form E1->*E2 is converted to its equivalent form, (*(E1)).*E2, so use of pointer-to-member expressions of either form behave equivalently in terms of undefined behavior.

    -

    Further, the C++ Standard, [expr.mptr.oper], paragraph 6, in part, states the following:

    +

    + A pointer-to-member expression of the form + + E1->*E2 + + is converted to its equivalent form, + + (*(E1)).*E2 + + , so use of pointer-to-member expressions of either form behave equivalently in terms of + + undefined behavior + + . +

    +

    + Further, the C++ Standard, + [expr.mptr.oper], paragraph 6,ย in part, states the following: +

    -

    If the second operand is the null pointer to member value, the behavior is undefined.

    +

    + If the second operand is the null pointer to member value,ย the behavior is undefined. +

    -

    Do not use a pointer-to-member expression where the dynamic type of the first operand does not contain the member to which the second operand refers, including the use of a null pointer-to-member value as the second operand.

    +

    + Do not use a pointer-to-member expression where the dynamic type of the first operand does not contain the member to which the second operand refers, including the use of a null pointer-to-member value as the second operand. +

    -

    In this noncompliant code example, a pointer-to-member object is obtained from D::g but is then upcast to be a B::*. When called on an object whose dynamic type is D, the pointer-to-member call is well defined. However, the dynamic type of the underlying object is B, which results in undefined behavior.

    - struct B { +

    + In this noncompliant code example, a pointer-to-member object is obtained from + + D::g + + butย is thenย upcast to be a + + B::* + + . When called on an object whose dynamic type is + + D + + , the pointer-to-member call is well defined. However, the dynamic type of the underlying objectย is + + B + + , which results in + + undefined behavior + + . +

    + + struct B { virtual ~B() = default; }; @@ -38,18 +176,29 @@ struct D : B { void f() { B *b = new B; - +ย  // ... - +ย  void (B::*gptr)() = static_cast<void(B::*)()>(&D::g); (b->*gptr)(); delete b; } - +
    -

    In this compliant solution, the upcast is removed, rendering the initial code ill-formed and emphasizing the underlying problem that B::g() does not exist. This compliant solution assumes that the programmer's intention was to use the correct dynamic type for the underlying object.

    - struct B { +

    + In this compliant solution, the upcast is removed, rendering the initial code + + ill-formed + + and emphasizing the underlying problem that + + B::g() + + does not exist. This compliant solution assumes that the programmer's intention was to use the correct dynamic type for the underlying object. +

    + + struct B { virtual ~B() = default; }; @@ -60,17 +209,24 @@ struct D : B { void f() { B *b = new D; // Corrected the dynamic object type. - +ย  // ... void (D::*gptr)() = &D::g; // Moved static_cast to the next line. (static_cast<D *>(b)->*gptr)(); delete b; } - +
    -

    In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in undefined behavior.

    - struct B { +

    + In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in + + undefined behavior + + . +

    + + struct B { virtual ~B() = default; }; @@ -78,39 +234,52 @@ struct D : B { virtual ~D() = default; virtual void g() { /* ... */ } }; - +ย  static void (D::*gptr)(); // Not explicitly initialized, defaults to nullptr. void call_memptr(D *ptr) { (ptr->*gptr)(); } - +ย  void f() { D *d = new D; call_memptr(d); delete d; -} +} +
    -

    In this compliant solution, gptr is properly initialized to a valid pointer-to-member value instead of to the default value of nullptr.

    - struct B { +

    + In this compliant solution, + + gptr + + is properly initialized to a valid pointer-to-member value instead of to the default value of + + nullptr + + . +

    + + struct B { virtual ~B() = default; }; - +ย  struct D : B { virtual ~D() = default; virtual void g() { /* ... */ } }; - +ย  static void (D::*gptr)() = &D::g; // Explicitly initialized. void call_memptr(D *ptr) { (ptr->*gptr)(); } - +ย  void f() { D *d = new D; call_memptr(d); delete d; -} +} +
    @@ -149,10 +318,14 @@ void f() { High @@ -185,7 +358,10 @@ void f() { 20.10 @@ -200,7 +376,9 @@ void f() { 7.2.0 @@ -215,7 +393,9 @@ void f() { 2021.2 @@ -230,7 +410,11 @@ void f() { 2021.4 @@ -245,7 +429,9 @@ void f() { 2021.2 @@ -284,10 +472,28 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - overflow_upon_dereferenceinvalid_function_pointer + + overflow_upon_dereference + invalid_function_pointer + - CertC++-OOP55 + + CertC++-OOP55 + - C++2810, C++2811, C++2812, C++2813, C++2814 + + C++2810, C++2811, C++2812, C++2813, C++2814 + - CERT.OOP.PTR_MEMBER.NO_MEMBER + + + CERT.OOP.PTR_MEMBER.NO_MEMBER + + - CERT_CPP-OOP55-a + + CERT_CPP-OOP55-a + A cast shall not convert a pointer to a function to any other pointer type, including a pointer to function type @@ -275,7 +461,9 @@ void f() { 4.4 - 2810, 2811, 2812, 2813, 2814 + + 2810, 2811, 2812, 2813, 2814 +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of EXP34-C. Do not dereference null pointers.

    +

    + + This rule is a subset of + + EXP34-C. Do not dereference null pointers + + . + +

    diff --git a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember-standard.qhelp b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember-standard.qhelp index 0f93c06587..e7d9026a70 100644 --- a/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember-standard.qhelp +++ b/cpp/cert/src/rules/OOP55-CPP/UseOfPointerToMemberToAccessUndefinedMember-standard.qhelp @@ -1,8 +1,27 @@
    -

    The pointer-to-member operators .* and ->* are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function f() on the object o.

    - struct S { +

    + The pointer-to-member operators + + .* + + and + + ->* + + are used to obtain an object or a function as though it were a member of an underlying object. For instance, the following are functionally equivalent ways to call the member function + + f() + + on the object + + o + + . +

    + + struct S { void f() {} }; @@ -12,22 +31,141 @@ void func() { o.f(); (o.*pm)(); -} -

    The call of the form o.f() uses class member access at compile time to look up the address of the function S::f() on the object o. The call of the form (o.*pm)() uses the pointer-to-member operator .* to call the function at the address specified by pm. In both cases, the object o is the implicit this object within the member function S::f().

    -

    The C++ Standard, [expr.mptr.oper], paragraph 4 [ISO/IEC 14882-2014], states the following:

    +} +
    +

    + The call of the form + + o.f() + + uses class member access at compile time to look up the address of the function + + S::f() + + on the object + + o + + . The call of the form + + (o.*pm)() + + uses the pointer-to-member operator + + .* + + to call the function at the address specified by + + pm + + . In both cases, the object + + o + + is the implicit + + this + + object within the member function + + S::f() + + . +

    +

    + The C++ Standard, [expr.mptr.oper], paragraph 4 + [ + + ISO/IEC 14882-2014 + + ] + , states + the following + : +

    -

    Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic type of E1 does not contain the member to which E2 refers, the behavior is undefined.

    +

    + Abbreviating + + pm-expression.*cast-expression + + as + + E1.*E2 + + , + + E1 + + is called the + + object expression + + . If the dynamicย type of + + E1 + + does not contain the member to which + + E2 + + refers, the behavior is undefined. +

    -

    A pointer-to-member expression of the form E1->*E2 is converted to its equivalent form, (*(E1)).*E2, so use of pointer-to-member expressions of either form behave equivalently in terms of undefined behavior.

    -

    Further, the C++ Standard, [expr.mptr.oper], paragraph 6, in part, states the following:

    +

    + A pointer-to-member expression of the form + + E1->*E2 + + is converted to its equivalent form, + + (*(E1)).*E2 + + , so use of pointer-to-member expressions of either form behave equivalently in terms of + + undefined behavior + + . +

    +

    + Further, the C++ Standard, + [expr.mptr.oper], paragraph 6,ย in part, states the following: +

    -

    If the second operand is the null pointer to member value, the behavior is undefined.

    +

    + If the second operand is the null pointer to member value,ย the behavior is undefined. +

    -

    Do not use a pointer-to-member expression where the dynamic type of the first operand does not contain the member to which the second operand refers, including the use of a null pointer-to-member value as the second operand.

    +

    + Do not use a pointer-to-member expression where the dynamic type of the first operand does not contain the member to which the second operand refers, including the use of a null pointer-to-member value as the second operand. +

    -

    In this noncompliant code example, a pointer-to-member object is obtained from D::g but is then upcast to be a B::*. When called on an object whose dynamic type is D, the pointer-to-member call is well defined. However, the dynamic type of the underlying object is B, which results in undefined behavior.

    - struct B { +

    + In this noncompliant code example, a pointer-to-member object is obtained from + + D::g + + butย is thenย upcast to be a + + B::* + + . When called on an object whose dynamic type is + + D + + , the pointer-to-member call is well defined. However, the dynamic type of the underlying objectย is + + B + + , which results in + + undefined behavior + + . +

    + + struct B { virtual ~B() = default; }; @@ -38,18 +176,29 @@ struct D : B { void f() { B *b = new B; - +ย  // ... - +ย  void (B::*gptr)() = static_cast<void(B::*)()>(&D::g); (b->*gptr)(); delete b; } - +
    -

    In this compliant solution, the upcast is removed, rendering the initial code ill-formed and emphasizing the underlying problem that B::g() does not exist. This compliant solution assumes that the programmer's intention was to use the correct dynamic type for the underlying object.

    - struct B { +

    + In this compliant solution, the upcast is removed, rendering the initial code + + ill-formed + + and emphasizing the underlying problem that + + B::g() + + does not exist. This compliant solution assumes that the programmer's intention was to use the correct dynamic type for the underlying object. +

    + + struct B { virtual ~B() = default; }; @@ -60,17 +209,24 @@ struct D : B { void f() { B *b = new D; // Corrected the dynamic object type. - +ย  // ... void (D::*gptr)() = &D::g; // Moved static_cast to the next line. (static_cast<D *>(b)->*gptr)(); delete b; } - +
    -

    In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in undefined behavior.

    - struct B { +

    + In this noncompliant code example, a null pointer-to-member value is passed as the second operand to a pointer-to-member expression, resulting in + + undefined behavior + + . +

    + + struct B { virtual ~B() = default; }; @@ -78,39 +234,52 @@ struct D : B { virtual ~D() = default; virtual void g() { /* ... */ } }; - +ย  static void (D::*gptr)(); // Not explicitly initialized, defaults to nullptr. void call_memptr(D *ptr) { (ptr->*gptr)(); } - +ย  void f() { D *d = new D; call_memptr(d); delete d; -} +} +
    -

    In this compliant solution, gptr is properly initialized to a valid pointer-to-member value instead of to the default value of nullptr.

    - struct B { +

    + In this compliant solution, + + gptr + + is properly initialized to a valid pointer-to-member value instead of to the default value of + + nullptr + + . +

    + + struct B { virtual ~B() = default; }; - +ย  struct D : B { virtual ~D() = default; virtual void g() { /* ... */ } }; - +ย  static void (D::*gptr)() = &D::g; // Explicitly initialized. void call_memptr(D *ptr) { (ptr->*gptr)(); } - +ย  void f() { D *d = new D; call_memptr(d); delete d; -} +} +
    @@ -149,10 +318,14 @@ void f() { High @@ -185,7 +358,10 @@ void f() { 20.10 @@ -200,7 +376,9 @@ void f() { 7.2.0 @@ -215,7 +393,9 @@ void f() { 2021.2 @@ -230,7 +410,11 @@ void f() { 2021.4 @@ -245,7 +429,9 @@ void f() { 2021.2 @@ -284,10 +472,28 @@ void f() {
    - P6 + + P6 + - L2 + + L2 +
    - overflow_upon_dereferenceinvalid_function_pointer + + overflow_upon_dereference + invalid_function_pointer + - CertC++-OOP55 + + CertC++-OOP55 + - C++2810, C++2811, C++2812, C++2813, C++2814 + + C++2810, C++2811, C++2812, C++2813, C++2814 + - CERT.OOP.PTR_MEMBER.NO_MEMBER + + + CERT.OOP.PTR_MEMBER.NO_MEMBER + + - CERT_CPP-OOP55-a + + CERT_CPP-OOP55-a + A cast shall not convert a pointer to a function to any other pointer type, including a pointer to function type @@ -275,7 +461,9 @@ void f() { 4.4 - 2810, 2811, 2812, 2813, 2814 + + 2810, 2811, 2812, 2813, 2814 +
    -

    Search for other vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for other + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    -

    This rule is a subset of EXP34-C. Do not dereference null pointers.

    +

    + + This rule is a subset of + + EXP34-C. Do not dereference null pointers + + . + +

    diff --git a/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements-standard.qhelp b/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements-standard.qhelp index a93982cc9e..a830c4012c 100644 --- a/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements-standard.qhelp +++ b/cpp/cert/src/rules/OOP56-CPP/HonorNewReplacementHandlerRequirements-standard.qhelp @@ -1,51 +1,203 @@
    -

    The handler functions new_handler, terminate_handler, and unexpected_handler can be globally replaced by custom implementations, as specified by [handler.functions], paragraph 2, of the C++ Standard [ISO/IEC 14882-2014]. For instance, an application could set a custom termination handler by calling std::set_terminate(), and the custom termination handler may log the termination for later auditing. However, the C++ Standard, [res.on.functions], paragraph 1, states the following:

    +

    + The + + handler + + functions + + new_handler + + , + + terminate_handler + + , and + + unexpected_handler + + can be globally replaced by custom + + implementations + + , as specified by [handler.functions], paragraph 2, of the C++ Standardย [ + + ISO/IEC 14882-2014 + + ]. For instance, an application could set a custom termination handler by calling + + std::set_terminate() + + , and the custom termination handler may log the termination for later auditing. However, the C++ Standard,ย [res.on.functions], paragraph 1, states the following: +

    -

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    +

    + In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. +

    -

    Paragraph 2, in part, further states the following:

    +

    + Paragraph 2, in part, further states the following: +

    -

    In particular, the effects are undefined in the following cases:โ€” for handler functions, if the installed handler function does not implement the semantics of the applicable Required behavior: paragraph

    +

    + In particular, the effects are undefined in the following cases: + โ€”ย for handler functions, if the installed handler function does not implementย the semantics of the applicable + + Required behavior: + + paragraph +

    -

    A replacement for any of the handler functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function.

    -

    New Handler

    -

    The requirements for a replacement new_handler are specified by [new.handler], paragraph 2:

    +

    + A replacement for any of the handler functions must meet the semantic requirements specified by the appropriate + + Required behavior: + + clause of the replaced function. +

    +

    + + New Handler + +

    +

    + The requirements for a replacement + + new_handler + + are specified by [new.handler], paragraph 2: +

    -

    Required behavior: A new_handler shall perform one of the following:โ€” make more storage available for allocation and then return;โ€” throw an exception of type bad_alloc or a class derived from bad_alloc;โ€” terminate execution of the program without returning to the caller;

    +

    + Required behavior: A + + new_handler + + shall perform one of the following: + โ€” make more storage available for allocation and then return; + โ€” throw an exception of type + + bad_alloc + + or a class derived from + + bad_alloc + + ; + โ€” terminate execution of the program without returning to the caller; +

    -

    Terminate Handler

    -

    The requirements for a replacement terminate_handler are specified by [terminate.handler], paragraph 2:

    +

    + + Terminate Handler + +

    +

    + The requirements for a replacement + + terminate_handler + + are specified byย [terminate.handler], paragraph 2: +

    -

    Required behavior: A terminate_handler shall terminate execution of the program without returning to the caller.

    +

    + Required behavior: + A + + terminate_handler + + shall terminate execution of the program without returningย to the caller. +

    -

    Unexpected Handler

    -

    The requirements for a replacement unexpected_handler are specified by [unexpected.handler], paragraph 2.

    +

    + + Unexpected Handler + +

    +

    + The requirements for a replacement + + unexpected_handler + + are specified byย [unexpected.handler], paragraph 2. +

    -

    Required behavior: An unexpected_handler shall not return. See also 15.5.2.

    +

    + Required behavior: + An + + unexpected_handler + + shall not return. See also 15.5.2. +

    -

    unexpected_handler is a deprecated feature of C++.

    +

    + + unexpected_handler + + is a deprecated feature of C++. +

    -

    In this noncompliant code example, a replacement new_handler is written to attempt to release salvageable resources when the dynamic memory manager runs out of memory. However, this example does not take into account the situation in which all salvageable resources have been recovered and there is still insufficient memory to satisfy the allocation request. Instead of terminating the replacement handler with an exception of type std::bad_alloc or terminating the execution of the program without returning to the caller, the replacement handler returns as normal. Under low memory conditions, an infinite loop will occur with the default implementation of ::operator new(). Because such conditions are rare in practice, it is likely for this bug to go undiscovered under typical testing scenarios.

    - #include <new> - +

    + In this noncompliant code example, a replacement + + new_handler + + is written to attempt to release salvageable resources when the dynamic memory manager runs out of memory. However, this example does not take into account the situation in which all salvageable resources have been recovered and there is still insufficient memory to satisfy the allocation request. Instead of terminating the replacement handler with an exception of type + + std::bad_alloc + + or terminating the execution of the program without returning to the caller, the replacement handler returns as normal. Under low memory conditions, an infinite loop will occur with the default implementation of + + ::operator new() + + . Because such conditions are rare in practice, it is likely for this bug to go undiscovered under typical testing scenarios. +

    + + #include <new> +ย  void custom_new_handler() { // Returns number of bytes freed. extern std::size_t reclaim_resources(); reclaim_resources(); } - +ย  int main() { std::set_new_handler(custom_new_handler); - +ย  // ... -} +} +
    -

    In this compliant solution, custom_new_handler() uses the return value from reclaim_resources(). If it returns 0, then there will be insufficient memory for operator new to succeed. Hence, an exception of type std::bad_alloc is thrown, meeting the requirements for the replacement handler.

    - #include <new> +

    + In this compliant solution, + + custom_new_handler() + + uses the return value from + + reclaim_resources() + + . If it returns + + 0 + + , then there will be insufficient memory for + + operator new + + to succeed. Hence,ย an exception of type + + std::bad_alloc + + is thrown, meeting the requirements for the replacement handler. +

    + + #include <new> void custom_new_handler() noexcept(false) { // Returns number of bytes freed. @@ -59,10 +211,17 @@ int main() { std::set_new_handler(custom_new_handler); // ... -} +} +
    -

    Failing to meet the required behavior for a replacement handler results in undefined behavior.

    +

    + Failing to meet the required behavior for a replacement handler results in + + undefined behavior + + . +

    @@ -99,10 +258,14 @@ int main() { High @@ -135,7 +298,9 @@ int main() { 2021.2 @@ -150,9 +315,15 @@ int main() { 2021.2
    - P2 + + P2 + - L3 + + L3 +
    - C++4776, C++4777, C++4778, C++4779 + + C++4776, C++4777, C++4778, C++4779 + - CERT_CPP-OOP56-a - CERT_CPP-OOP56-b - CERT_CPP-OOP56-c + + CERT_CPP-OOP56-a + + + CERT_CPP-OOP56-b + + + CERT_CPP-OOP56-c + Properly define terminate handlers @@ -164,7 +335,17 @@ int main() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -198,13 +379,19 @@ int main() { diff --git a/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements-standard.qhelp b/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements-standard.qhelp index a93982cc9e..a830c4012c 100644 --- a/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements-standard.qhelp +++ b/cpp/cert/src/rules/OOP56-CPP/HonorTerminationReplacementHandlerRequirements-standard.qhelp @@ -1,51 +1,203 @@
    -

    The handler functions new_handler, terminate_handler, and unexpected_handler can be globally replaced by custom implementations, as specified by [handler.functions], paragraph 2, of the C++ Standard [ISO/IEC 14882-2014]. For instance, an application could set a custom termination handler by calling std::set_terminate(), and the custom termination handler may log the termination for later auditing. However, the C++ Standard, [res.on.functions], paragraph 1, states the following:

    +

    + The + + handler + + functions + + new_handler + + , + + terminate_handler + + , and + + unexpected_handler + + can be globally replaced by custom + + implementations + + , as specified by [handler.functions], paragraph 2, of the C++ Standardย [ + + ISO/IEC 14882-2014 + + ]. For instance, an application could set a custom termination handler by calling + + std::set_terminate() + + , and the custom termination handler may log the termination for later auditing. However, the C++ Standard,ย [res.on.functions], paragraph 1, states the following: +

    -

    In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on the implementation.

    +

    + In certain cases (replacement functions, handler functions, operations on types used to instantiate standardย library template components), the C++ standard library depends on components supplied by a C++ program. If these components do not meet their requirements, the Standard places no requirements on theย implementation. +

    -

    Paragraph 2, in part, further states the following:

    +

    + Paragraph 2, in part, further states the following: +

    -

    In particular, the effects are undefined in the following cases:โ€” for handler functions, if the installed handler function does not implement the semantics of the applicable Required behavior: paragraph

    +

    + In particular, the effects are undefined in the following cases: + โ€”ย for handler functions, if the installed handler function does not implementย the semantics of the applicable + + Required behavior: + + paragraph +

    -

    A replacement for any of the handler functions must meet the semantic requirements specified by the appropriate Required behavior: clause of the replaced function.

    -

    New Handler

    -

    The requirements for a replacement new_handler are specified by [new.handler], paragraph 2:

    +

    + A replacement for any of the handler functions must meet the semantic requirements specified by the appropriate + + Required behavior: + + clause of the replaced function. +

    +

    + + New Handler + +

    +

    + The requirements for a replacement + + new_handler + + are specified by [new.handler], paragraph 2: +

    -

    Required behavior: A new_handler shall perform one of the following:โ€” make more storage available for allocation and then return;โ€” throw an exception of type bad_alloc or a class derived from bad_alloc;โ€” terminate execution of the program without returning to the caller;

    +

    + Required behavior: A + + new_handler + + shall perform one of the following: + โ€” make more storage available for allocation and then return; + โ€” throw an exception of type + + bad_alloc + + or a class derived from + + bad_alloc + + ; + โ€” terminate execution of the program without returning to the caller; +

    -

    Terminate Handler

    -

    The requirements for a replacement terminate_handler are specified by [terminate.handler], paragraph 2:

    +

    + + Terminate Handler + +

    +

    + The requirements for a replacement + + terminate_handler + + are specified byย [terminate.handler], paragraph 2: +

    -

    Required behavior: A terminate_handler shall terminate execution of the program without returning to the caller.

    +

    + Required behavior: + A + + terminate_handler + + shall terminate execution of the program without returningย to the caller. +

    -

    Unexpected Handler

    -

    The requirements for a replacement unexpected_handler are specified by [unexpected.handler], paragraph 2.

    +

    + + Unexpected Handler + +

    +

    + The requirements for a replacement + + unexpected_handler + + are specified byย [unexpected.handler], paragraph 2. +

    -

    Required behavior: An unexpected_handler shall not return. See also 15.5.2.

    +

    + Required behavior: + An + + unexpected_handler + + shall not return. See also 15.5.2. +

    -

    unexpected_handler is a deprecated feature of C++.

    +

    + + unexpected_handler + + is a deprecated feature of C++. +

    -

    In this noncompliant code example, a replacement new_handler is written to attempt to release salvageable resources when the dynamic memory manager runs out of memory. However, this example does not take into account the situation in which all salvageable resources have been recovered and there is still insufficient memory to satisfy the allocation request. Instead of terminating the replacement handler with an exception of type std::bad_alloc or terminating the execution of the program without returning to the caller, the replacement handler returns as normal. Under low memory conditions, an infinite loop will occur with the default implementation of ::operator new(). Because such conditions are rare in practice, it is likely for this bug to go undiscovered under typical testing scenarios.

    - #include <new> - +

    + In this noncompliant code example, a replacement + + new_handler + + is written to attempt to release salvageable resources when the dynamic memory manager runs out of memory. However, this example does not take into account the situation in which all salvageable resources have been recovered and there is still insufficient memory to satisfy the allocation request. Instead of terminating the replacement handler with an exception of type + + std::bad_alloc + + or terminating the execution of the program without returning to the caller, the replacement handler returns as normal. Under low memory conditions, an infinite loop will occur with the default implementation of + + ::operator new() + + . Because such conditions are rare in practice, it is likely for this bug to go undiscovered under typical testing scenarios. +

    + + #include <new> +ย  void custom_new_handler() { // Returns number of bytes freed. extern std::size_t reclaim_resources(); reclaim_resources(); } - +ย  int main() { std::set_new_handler(custom_new_handler); - +ย  // ... -} +} +
    -

    In this compliant solution, custom_new_handler() uses the return value from reclaim_resources(). If it returns 0, then there will be insufficient memory for operator new to succeed. Hence, an exception of type std::bad_alloc is thrown, meeting the requirements for the replacement handler.

    - #include <new> +

    + In this compliant solution, + + custom_new_handler() + + uses the return value from + + reclaim_resources() + + . If it returns + + 0 + + , then there will be insufficient memory for + + operator new + + to succeed. Hence,ย an exception of type + + std::bad_alloc + + is thrown, meeting the requirements for the replacement handler. +

    + + #include <new> void custom_new_handler() noexcept(false) { // Returns number of bytes freed. @@ -59,10 +211,17 @@ int main() { std::set_new_handler(custom_new_handler); // ... -} +} +
    -

    Failing to meet the required behavior for a replacement handler results in undefined behavior.

    +

    + Failing to meet the required behavior for a replacement handler results in + + undefined behavior + + . +

    Subclause 17.6.4.8, "Other Functions" Subclause 18.6.2.3, "Type - new_handler + + new_handler + " Subclause 18.8.3.1, "Type - terminate_handler + + terminate_handler + " Subclause D.11.1, "Type - unexpected_handler + + unexpected_handler + "
    @@ -99,10 +258,14 @@ int main() { High @@ -135,7 +298,9 @@ int main() { 2021.2 @@ -150,9 +315,15 @@ int main() { 2021.2
    - P2 + + P2 + - L3 + + L3 +
    - C++4776, C++4777, C++4778, C++4779 + + C++4776, C++4777, C++4778, C++4779 + - CERT_CPP-OOP56-a - CERT_CPP-OOP56-b - CERT_CPP-OOP56-c + + CERT_CPP-OOP56-a + + + CERT_CPP-OOP56-b + + + CERT_CPP-OOP56-c + Properly define terminate handlers @@ -164,7 +335,17 @@ int main() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -198,13 +379,19 @@ int main() { diff --git a/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions-standard.qhelp b/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions-standard.qhelp index 624f55f980..45f9596602 100644 --- a/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions-standard.qhelp +++ b/cpp/cert/src/rules/OOP57-CPP/PreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions-standard.qhelp @@ -1,16 +1,81 @@
    -

    Several C standard library functions perform bytewise operations on objects. For instance, std::memcmp() compares the bytes comprising the object representation of two objects, and std::memcpy() copies the bytes comprising an object representation into a destination buffer. However, for some object types, it results in undefined or abnormal program behavior.

    -

    The C++ Standard, [class], paragraph 6 [ISO/IEC 14882-2014], states the following:

    +

    + Several C standard library functions perform bytewise operations on objects. For instance, + + std::memcmp() + + compares the bytes comprising the object representation of two objects, and + + std::memcpy() + + copies the bytes comprising an object representation into a destination buffer. However, for some object types, it results in undefined or abnormal program behavior. +

    +

    + The C++ Standard,ย [class], paragraph 6 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    A trivially copyable class is a class that: โ€” has no non-trivial copy constructors, โ€” has no non-trivial move constructors, โ€” has no non-trivial copy assignment operators, โ€” has no non-trivial move assignment operators, and โ€” has a trivial destructor.A trivial class is a class that has a default constructor, has no non-trivial default constructors, and is trivially copyable. [Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base classes. โ€” end note]

    +

    + A + + trivially copyable class + + is a class that: + โ€” has no non-trivial copy constructors, + โ€” has no non-trivial move constructors, + โ€” has no non-trivial copy assignment operators, + โ€” has no non-trivial move assignment operators, and + โ€” has a trivial destructor. + A + + trivial class + + is a class that has a default constructor, has no non-trivial default constructors,ย and is trivially copyable. + [ + Note: + In particular, a trivially copyable or trivial class does not have virtual functions or virtual baseย classes. + โ€” end note + ] +

    -

    Additionally, the C++ Standard, [class], paragraph 7, states the following:

    +

    + Additionally, the C++ Standard, [class], paragraph 7, states the following: +

    -

    A standard-layout class is a class that: โ€” has no non-static data members of type non-standard-layout class (or array of such types) or reference, โ€” has no virtual functions and no virtual base classes, โ€” has the same access control for all non-static data members, โ€” has no non-standard-layout base classes, โ€” either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and โ€” has no base classes of the same type as the first non-static data member.

    +

    + A + + standard-layout class + + is a class that: + โ€” has no non-static data members of type non-standard-layout class (or array of such types) or reference, + โ€” has no virtual functions and no virtual base classes, + โ€” has the same access control for all non-static data members, + โ€” has no non-standard-layout base classes, + โ€” either has no non-static data members in the most derived class and at most one base class withย non-static data members, or has no base classes with non-static data members, and + โ€” has no base classes of the same type as the first non-static data member. +

    -

    Do not use std::memset() to initialize an object of nontrivial class type as it may not properly initialize the value representation of the object. Do not use std::memcpy() (or related bytewise copy functions) to initialize a copy of an object of nontrivial class type, as it may not properly initialize the value representation of the copy. Do not use std::memcmp() (or related bytewise comparison functions) to compare objects of nonstandard-layout class type, as it may not properly compare the value representations of the objects. In all cases, it is best to prefer the alternatives.

    +

    + Do not use + + std::memset() + + to initialize an object of nontrivial class type as it may not properly initialize the value representation of the object. Do not use + + std::memcpy() + + (or related bytewise copy functions) to initialize a copy of an object of nontrivial class type, as it may not properly initialize the value representation of the copy. Do not use + + std::memcmp() + + (or related bytewise comparison functions) to compare objects of nonstandard-layout class type, as it may not properly compare the value representations of the objects. In all cases, it is best to prefer the alternatives. +

    Subclause 17.6.4.8, "Other Functions" Subclause 18.6.2.3, "Type - new_handler + + new_handler + " Subclause 18.8.3.1, "Type - terminate_handler + + terminate_handler + " Subclause D.11.1, "Type - unexpected_handler + + unexpected_handler + "
    @@ -23,7 +88,9 @@
    - std::memset() + + std::memset() + Class constructor @@ -31,42 +98,69 @@
    - std::memcpy() - std::memmove() - std::strcpy() + + std::memcpy() + + + std::memmove() + + + std::strcpy() + Class copy constructor or - operator=() + + operator=() +
    - std::memcmp() - std::strcmp() + + std::memcmp() + + + std::strcmp() + - operator<() + + operator<() + , - operator>() + + operator>() + , - operator==() + + operator==() + , or - operator!=() + + operator!=() +
    -

    In this noncompliant code example, a nontrivial class object is initialized by calling its default constructor but is later reinitialized to its default state using std::memset(), which does not properly reinitialize the object. Improper reinitialization leads to class invariants not holding in later uses of the object.

    - #include <cstring> +

    + In this noncompliant code example, a nontrivial class object is initialized by calling its default constructor but is later reinitialized to its default state using + + std::memset() + + , which does not properly reinitialize the object. Improper reinitialization leads to class invariants not holding in later uses of the object. +

    + + #include <cstring> #include <iostream> - +ย  class C { int scalingFactor; int otherData; - +ย  public: C() : scalingFactor(1) {} @@ -76,7 +170,7 @@ public: } // ... }; - +ย  void f() { C c; @@ -86,18 +180,40 @@ void f() { std::memset(&c, 0, sizeof(C)); std::cout << c.f(100) << std::endl; -} -

    The above noncompliant code example is compliant with EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation because all of the bits in the value representation are also used in the object representation of C.

    +} +
    +

    + The above noncompliant code example is compliant with + + EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation + + because all of the bits in the value representation are also used in the object representation of + + C + + . +

    -

    In this compliant solution, the call to std::memset() is replaced with a default-initialized copy-and-swap operation called clear(). This operation ensures that the object is initialized to its default state properly, and it behaves properly for object types that have optimized assignment operators that fail to clear all data members of the object being assigned into.

    - #include <iostream> +

    + In this compliant solution, the call to + + std::memset() + + is replaced with a default-initialized copy-and-swap operation called + + clear() + + . This operation ensures that the object is initialized to its default state properly, and it behaves properly for object types that have optimized assignment operators that fail to clear all data members of the object being assigned into. +

    + + #include <iostream> #include <utility> - +ย  class C { int scalingFactor; int otherData; - +ย  public: C() : scalingFactor(1) {} @@ -107,7 +223,7 @@ public: } // ... }; - +ย  template <typename T> T& clear(T &o) { using std::swap; @@ -125,35 +241,75 @@ void f() { clear(c); std::cout << c.f(100) << std::endl; -} +} +
    -

    In this noncompliant code example, std::memcpy() is used to create a copy of an object of nontrivial type C. However, because each object instance attempts to delete the int * in C::~C(), double-free vulnerabilities may occur because the same pointer value will be copied into c2.

    - #include <cstring> - +

    + In this noncompliant code example, + + std::memcpy() + + is used to create a copy of an object of nontrivial type + + C + + . However, becauseย each object instance attempts to delete the + + int * + + in + + C::~C() + + , double-free + + vulnerabilities + + may occur because the same pointer value will be copied into + + c2 + + . +

    + + #include <cstring> +ย  class C { int *i; - +ย  public: C() : i(nullptr) {} ~C() { delete i; } - +ย  void set(int val) { if (i) { delete i; } i = new int{val}; } - +ย  // ... }; - +ย  void f(C &c1) { C c2; std::memcpy(&c2, &c1, sizeof(C)); -} +} +
    -

    In this compliant solution, C defines an assignment operator that is used instead of calling std::memcpy().

    - class C { +

    + In this compliant solution, + + C + + defines an assignment operator that is used instead of calling + + std::memcpy() + + . +

    + + class C { int *i; public: @@ -184,12 +340,36 @@ public: void f(C &c1) { C c2 = c1; -} +} +
    -

    In this noncompliant code example, std::memcmp() is used to compared two objects of nonstandard-layout type. Because std::memcmp() performs a bytewise comparison of the object representations, if the implementation uses a vtable pointer as part of the object representation, it will compare vtable pointers. If the dynamic type of either c1 or c2 is a derived class of type C, the comparison may fail despite the value representation of either object.

    - #include <cstring> - +

    + In this noncompliant code example, + + std::memcmp() + + is used to compared two objects of nonstandard-layout type. Because + + std::memcmp() + + performs a bytewise comparison of the object representations, if the implementation uses a vtable pointer as part of the object representation, it will compare vtable pointers. If the dynamic type of either + + c1 + + or + + c2 + + is a derived class of type + + C + + , the comparison may fail despite the value representation of either object. +

    + + #include <cstring> +ย  class C { int i; @@ -203,17 +383,39 @@ void f(C &c1, C &c2) { if (!std::memcmp(&c1, &c2, sizeof(C))) { // ... } -} -

    Because a vtable is not part of an object's value representation, comparing it with std::memcmp() also violates EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation.

    +} +
    +

    + Because a vtable is not part of an object's value representation, comparing it with + + std::memcmp() + + also violates + + EXP62-CPP. Do not access the bits of an object representation that are not part of the object's value representation + + . +

    -

    In this compliant solution, C defines an equality operator that is used instead of calling std::memcmp(). This solution ensures that only the value representation of the objects is considered when performing the comparison.

    - class C { +

    + In this compliant solution, + + C + + defines an equality operator that is used instead of calling + + std::memcmp() + + . This solution ensures that only the value representation of the objects is considered when performing the comparison. +

    + + class C { int i; public: virtual void f(); - + ย  bool operator==(const C &rhs) const { return rhs.i == i; } @@ -225,10 +427,21 @@ void f(C &c1, C &c2) { if (c1 == c2) { // ... } -} +} +
    -

    Most violations of this rule will result in abnormal program behavior. However, overwriting implementation details of the object representation can lead to code execution vulnerabilities.

    +

    + Most violations of this rule will result in abnormal program behavior. However, overwriting + + implementation + + details of the object representation can lead to code execution + + vulnerabilities + + . +

    @@ -265,10 +478,14 @@ void f(C &c1, C &c2) { High @@ -301,30 +518,19 @@ void f(C &c1, C &c2) { 20.10 - - - - - - @@ -350,7 +558,11 @@ void f(C &c1, C &c2) { 2021.4 @@ -364,7 +576,9 @@ void f(C &c1, C &c2) { @@ -428,12 +648,20 @@ void f(C &c1, C &c2) { @@ -448,7 +676,16 @@ void f(C &c1, C &c2) { 20.10
    - P6 + + P6 + - L2 + + L2 +
    - stdlib-use-atostdlib-usestdlib-use-getenvstdlib-use-systeminclude-timestdlib-use-string-unbounded + + stdlib-use-ato + stdlib-use + stdlib-use-getenv + stdlib-use-system + include-time + stdlib-use-string-unbounded + Partially checked
    - - CodeSonar - - - 6.2p0 - - BADFUNC.MEMCMP - BADFUNC.MEMSET - - Use of memcmp - Use of memset -
    @@ -335,7 +541,9 @@ void f(C &c1, C &c2) { 2021.2 - C++5017, C++5038 + + C++5017, C++5038 + - CERT.OOP.CSTD_FUNC_USE + + + CERT.OOP.CSTD_FUNC_USE + + - 44 S + + 44 S + Enhanced Enforcement @@ -380,8 +594,12 @@ void f(C &c1, C &c2) { 2021.2 - CERT_CPP-OOP57-a - CERT_CPP-OOP57-b + + CERT_CPP-OOP57-a + + + CERT_CPP-OOP57-b + Do not initialize objects with a non-trivial class type using C standard library functions @@ -416,7 +634,9 @@ void f(C &c1, C &c2) { 4.4 - 5017, 5038 + + 5017, 5038 + - 7.17 + 7.16 - V598 + + V598 + + + , - V780 + + + V780 + + - stdlib-use-atostdlib-usestdlib-use-getenvstdlib-use-systeminclude-timestdlib-use-string-unbounded + + + stdlib-use-ato + stdlib-use + stdlib-use-getenv + stdlib-use-system + include-time + stdlib-use-string-unbounded + + Partially checked @@ -458,7 +695,17 @@ void f(C &c1, C &c2) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject-standard.qhelp b/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject-standard.qhelp index befff420e6..4d6ca63083 100644 --- a/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject-standard.qhelp +++ b/cpp/cert/src/rules/OOP58-CPP/CopyOperationsMustNotMutateTheSourceObject-standard.qhelp @@ -1,12 +1,60 @@
    -

    Copy operations (copy constructors and copy assignment operators) are expected to copy the salient properties of a source object into the destination object, with the resulting object being a "copy" of the original. What is considered to be a salient property of the type is type-dependent, but for types that expose comparison or equality operators, includes any properties used for those comparison operations. This expectation leads to assumptions in code that a copy operation results in a destination object with a value representation that is equivalent to the source object value representation. Violation of this basic assumption can lead to unexpected behavior.

    -

    Ideally, the copy operator should have an idiomatic signature. For copy constructors, that is T(const T&); and for copy assignment operators, that is T& operator=(const T&);. Copy constructors and copy assignment operators that do not use an idiomatic signature do not meet the requirements of the CopyConstructible or CopyAssignable concept, respectively. This precludes the type from being used with common standard library functionality [ISO/IEC 14882-2014].

    -

    When implementing a copy operator, do not mutate any externally observable members of the source object operand or globally accessible information. Externally observable members include, but are not limited to, members that participate in comparison or equality operations, members whose values are exposed via public APIs, and global variables.

    -

    Before C++11, a copy operation that mutated the source operand was the only way to provide move-like semantics. However, the language did not provide a way to enforce that this operation only occurred when the source operand was at the end of its lifetime, which led to fragile APIs like std::auto_ptr. In C++11 and later, such a situation is a good candidate for a move operation instead of a copy operation.

    -

    auto_ptr

    -

    For example, in C++03, std::auto_ptr had the following copy operation signatures [ISO/IEC 14882-2003]:

    +

    + Copy operations (copy constructors and copy assignment operators) are expected to copy the salient properties of a source object into the destination object, with the resulting object being a "copy" of the original. What is considered to be a salient property of the type is type-dependent, but for types that expose comparison or equality operators, includes any properties used for those comparison operations. This expectation leads to assumptions in code that a copy operation results in a destination object with a value representation that is equivalent to the source object value representation. Violation of this basic assumption can lead to unexpected behavior. +

    +

    + Ideally, the copy operator should have an idiomatic signature. For copy constructors, that is + + T(const T&); + + and for copy assignment operators, that is + + T& operator=(const T&); + + . Copy constructors and copy assignment operators that do not use an idiomatic signature do not meet the requirements of the + + CopyConstructible + + or + + CopyAssignable + + concept, respectively. This precludes the type from being used with common standard library functionality [ + + ISO/IEC 14882-2014 + + ]. +

    +

    + When implementing a copy operator, do not mutate any externally observable members of the source object operand or globally accessible information. Externally observable members include, but are not limited to, members that participate in comparison or equality operations, members whose values are exposed via public APIs, and global variables. +

    +

    + Before C++11, a copy operation that mutated the source operand was the only way to provide move-like semantics. However, the language did not provide a way to enforce that this operation only occurred when the source operand was at the end of its lifetime, which led to fragile APIs like + + std::auto_ptr + + . In C++11 and later, such a situation is a good candidate for a move operation instead of a copy operation. +

    +

    + + auto_ptr + +

    +

    + For example, in C++03, + + std::auto_ptr + + had the following copy operation signatures + [ + + ISO/IEC 14882-2003 + + ] + : +

    @@ -14,7 +62,9 @@ Copy constructor @@ -22,20 +72,129 @@ Copy assignment
    - auto_ptr(auto_ptr &A); + + auto_ptr(auto_ptr &A); +
    - auto_ptr& operator=(auto_ptr &A); + + auto_ptr& operator=(auto_ptr &A); +
    -

    Both copy construction and copy assignment would mutate the source argument, A, by effectively calling this->reset(A.release()). However, this invalidated assumptions made by standard library algorithms such as std::sort(), which may need to make a copy of an object for later comparisons [Hinnant 05]. Consider the following implementation of std::sort() that implements the quick sort algorithm.

    - // ... +

    + Both copy construction and copy assignment would mutate the source argument, + + A + + , by effectively calling + + this->reset(A.release()) + + . However, this invalidated assumptions made by standard library algorithms such as + + std::sort() + + , which may need to make a copy of an object for later comparisons + [ + + Hinnant 05 + + ] + . Consider the followingย implementation of + + std::sort() + + that implements the + + quick sort + + algorithm. +

    + + // ... value_type pivot_element = *mid_point; -// ... -

    At this point, the sorting algorithm assumes that pivot_element and *mid_point have equivalent value representations and will compare equal. However, for std::auto_ptr, this is not the case because *mid_point has been mutated and results in unexpected behavior.

    -

    In C++11, the std::unique_ptr smart pointer class was introduced as a replacement for std::auto_ptr to better specify the ownership semantics of pointer objects. Rather than mutate the source argument in a copy operation, std::unique_ptr explicitly deletes the copy constructor and copy assignment operator, and instead uses a move constructor and move assignment operator. Subsequently, std::auto_ptr was deprecated in C++11.

    -

    Noncompliant Code Example

    -

    In this noncompliant code example, the copy operations for A mutate the source operand by resetting its member variable m to 0. When std::fill() is called, the first element copied will have the original value of obj.m, 12, at which point obj.m is set to 0. The subsequent nine copies will all retain the value 0.

    - #include <algorithm> +// ... + +

    + At this point, the sorting algorithm assumes that + + pivot_element + + and + + *mid_point + + have equivalent value representations and will compare equal. However, for + + std::auto_ptr + + , this is not the case because + + *mid_point + + has been mutatedย and results in unexpected behavior. +

    +

    + In C++11, the + + std::unique_ptr + + smart pointer class was introduced as a replacement for + + std::auto_ptr + + to better specify the ownership semantics of pointer objects. Rather than mutate the source argument in a copy operation, + + std::unique_ptr + + explicitly deletes the copy constructor and copy assignment operator, and instead uses a move constructor and move assignment operator. Subsequently, + + std::auto_ptr + + was deprecated in C++11. +

    +

    + Noncompliant Code Example +

    +

    + In this noncompliant code example, the copy operations for + + A + + mutate the source operand by resetting its member variable + + m + + to + + 0 + + . When + + std::fill() + + is called, the first element copied will have the original value of + + obj.m + + , + + 12 + + , at which point + + obj.m + + is set to + + 0 + + . The subsequent nine copies will all retain the value + + 0 + + . +

    + + #include <algorithm> #include <vector> class A { @@ -56,7 +215,7 @@ public: } return *this; } - + ย  int get_m() const { return m; } }; @@ -64,11 +223,27 @@ void f() { std::vector<A> v{10}; A obj(12); std::fill(v.begin(), v.end(), obj); -} +} +
    -

    In this compliant solution, the copy operations for A no longer mutate the source operand, ensuring that the vector contains equivalent copies of obj. Instead, A has been given move operations that perform the mutation when it is safe to do so.

    - #include <algorithm> +

    + In this compliant solution, the copy operations for + + A + + no longer mutate the source operand, ensuring that the vector contains equivalent copies of + + obj + + . Instead, + + A + + has been given move operations that perform the mutation when it is safe to do so. +

    + + #include <algorithm> #include <vector> class A { @@ -87,7 +262,7 @@ public: } return *this; } - +ย  A& operator=(A &&other) { m = other.m; other.m = 0; @@ -101,13 +276,29 @@ void f() { std::vector<A> v{10}; A obj(12); std::fill(v.begin(), v.end(), obj); -} +} +
    -

    OOP58-CPP-EX0: Reference counting, and implementations such as std::shared_ptr<> constitute an exception to this rule. Any copy or assignment operation of a reference-counted object requires the reference count to be incremented. The semantics of reference counting are well-understood, and it can be argued that the reference count is not a salient part of the shared_pointer object.

    +

    + + OOP58-CPP-EX0: + + Reference counting, and implementations such as + + std::shared_ptr<> + + constitute an exception to this rule. Any copy or assignment operation of a reference-counted object requires the reference count to be incremented. The semantics of reference counting are well-understood, and it can be argued that the reference count is not a salient part of the + + shared_pointer + + object. +

    -

    Copy operations that mutate the source operand or global state can lead to unexpected program behavior. Using such a type in a Standard Template Library container or algorithm can also lead to undefined behavior.

    +

    + Copy operations that mutate the source operand or global state can lead to unexpected program behavior. Using such a type in a Standard Template Library container or algorithm can also lead to undefined behavior. +

    @@ -144,10 +335,14 @@ void f() { Low @@ -180,7 +375,9 @@ void f() { 2021.2 @@ -195,7 +392,11 @@ void f() { 2021.4 @@ -210,7 +411,9 @@ void f() { 2021.2 @@ -253,7 +458,17 @@ void f() {
    - P9 + + P9 + - L2 + + L2 +
    - C++4075 + + C++4075 + - CERT.OOP.COPY_MUTATES + + + CERT.OOP.COPY_MUTATES + + - CERT_CPP-OOP58-a + + CERT_CPP-OOP58-a + Copy operations must not mutate the source object @@ -244,7 +447,9 @@ void f() { 4.4 - 4075 + + 4075 +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert-standard.qhelp b/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert-standard.qhelp index 8ca1ca0627..63c03b5478 100644 --- a/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert-standard.qhelp +++ b/cpp/cert/src/rules/STR50-CPP/BasicStringMayNotBeNullTerminatedCert-standard.qhelp @@ -1,50 +1,148 @@
    -

    Copying data to a buffer that is not large enough to hold that data results in a buffer overflow. Buffer overflows occur frequently when manipulating strings [Seacord 2013]. To prevent such errors, either limit copies through truncation or, preferably, ensure that the destination is of sufficient size to hold the data to be copied. C-style strings require a null character to indicate the end of the string, while the C++ std::basic_string template requires no such character.

    +

    + Copying data to a buffer that is not large enough to hold that data results in a buffer overflow. Buffer overflows occur frequently when manipulating strings [ + + Seacord 2013 + + ]. To prevent such errors, eitherย limit copies through truncation or, preferably, ensure that the destination is of sufficient size to hold the data to be copied. C-style strings require a null character to indicate the end of the string, while the C++ + + std::basic_string + + template requires no such character. +

    -

    Because the input is unbounded, the following code could lead to a buffer overflow.

    - #include <iostream> - +

    + Because the input is unbounded, the following code could lead to a buffer overflow. +

    + + #include <iostream> +ย  void f() { char buf[12]; std::cin >> buf; -} +} +
    -

    To solve this problem, it may be tempting to use the std::ios_base::width() method, but there still is a trap, as shown in this noncompliant code example.

    - #include <iostream> - +

    + To solve this problem, it may be tempting to use the + + std::ios_base::width() + + method, but there still is a trap, as shown in this noncompliant code example. +

    + + #include <iostream> +ย  void f() { char bufOne[12]; char bufTwo[12]; std::cin.width(12); std::cin >> bufOne; std::cin >> bufTwo; -} -

    In this example, the first read will not overflow, but could fill bufOne with a truncated string. Furthermore, the second read still could overflow bufTwo. The C++ Standard, [istream.extractors], paragraphs 7โ€“9 [ISO/IEC 14882-2014], describes the behavior of operator>>(basic_istream &, charT *) and, in part, states the following:

    +} +
    +

    + In this example, the first read will not overflow, but could fill + + bufOne + + with a truncated string. Furthermore, the second read still could overflow + + bufTwo + + . The C++ Standard, [istream.extractors], paragraphs 7โ€“9 ย [ + + ISO/IEC 14882-2014 + + ], describes the behavior of + + operator>>(basic_istream &, charT *) + + and, in part, states the following: +

    -

    operator>> then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted. operator>> then calls width(0).

    +

    + + operator>> + + then stores a null byte ( + + charT() + + ) in the next position, which may be the first position ifย no characters were extracted. + + operator>> + + then calls + + width(0) + + . +

    -

    Consequently, it is necessary to call width() prior to each operator>> call passing a bounded array. However, this does not account for the input being truncated, which may lead to information loss or a possible vulnerability.

    +

    + Consequently, it is necessary to call + + width() + + prior to each + + operator>> + + call passing a bounded array. However, this does not account for the input being truncated, which may lead to information loss or a possible + + vulnerability + + . +

    -

    The best solution for ensuring that data is not truncated and for guarding against buffer overflows is to use std::string instead of a bounded array, as in this compliant solution.

    - #include <iostream> +

    + The best solution for ensuring that data is not truncated and for guarding against buffer overflows is to use + + std::string + + instead of a bounded array, as in this compliant solution. +

    + + #include <iostream> #include <string> - +ย  void f() { std::string input; std::string stringOne, stringTwo; std::cin >> stringOne >> stringTwo; -} +} +
    -

    In this noncompliant example, the unformatted input function std::basic_istream<T>::read() is used to read an unformatted character array of 32 characters from the given file. However, the read() function does not guarantee that the string will be null terminated, so the subsequent call of the std::string constructor results in undefined behavior if the character array does not contain a null terminator.

    - #include <fstream> +

    + In this noncompliant example, the unformatted input function + + std::basic_istream<T>::read() + + is used to read an unformatted character array of 32 characters from the given file. However, the + + read() + + function does not guarantee that the string will be null terminated, so the subsequent call of the + + std::string + + constructor results in + + undefined behavior + + if the character array does not contain a null terminator. +

    + + #include <fstream> #include <string> - +ย  void f(std::istream &in) { char buffer[32]; try { @@ -55,11 +153,23 @@ void f(std::istream &in) { std::string str(buffer); // ... -} +} +
    -

    This compliant solution assumes that the input from the file is at most 32 characters. Instead of inserting a null terminator, it constructs the std::string object based on the number of characters read from the input stream. If the size of the input is uncertain, it is better to use std::basic_istream<T>::readsome() or a formatted input function, depending on need.

    - #include <fstream> +

    + This compliant solution assumes that the input from the file is at most 32 characters. Instead of inserting a null terminator, it constructs the + + std::string + + object based on the number of characters read from the input stream. If the size of the input is uncertain, it is better to use + + std::basic_istream<T>::readsome() + + or a formatted input function, depending on need. +

    + + #include <fstream> #include <string> void f(std::istream &in) { @@ -71,10 +181,17 @@ void f(std::istream &in) { } std::string str(buffer, in.gcount()); // ... -} +} +
    -

    Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code with the permissions of the vulnerable process.

    +

    + Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can + + exploit + + this condition to execute arbitrary code with the permissions of the vulnerable process. +

    @@ -111,10 +228,14 @@ void f(std::istream &in) { Medium @@ -144,11 +265,16 @@ void f(std::istream &in) { @@ -181,10 +309,18 @@ void f(std::istream &in) { 2021.4 @@ -198,7 +334,9 @@ void f(std::istream &in) { @@ -258,7 +406,11 @@ void f(std::istream &in) { 4.10 @@ -267,7 +419,17 @@ void f(std::istream &in) {
    - P18 + + P18 + - L1 + + L1 +
    - 6.2p0 + 6.1p0 - MISC.MEM.NTERM - LANG.MEM.BOLANG.MEM.TO + + MISC.MEM.NTERM + + + LANG.MEM.BO + LANG.MEM.TO + No space for null terminator @@ -166,7 +292,9 @@ void f(std::istream &in) { 2021.2 - C++2835, C++2836, C++2839, C++5216 + + C++2835, C++2836, C++2839, C++5216 + - NNTS.MIGHT - NNTS.TAINTED - NNTS.MUST - SV.UNBOUND_STRING_INPUT.CIN + + NNTS.MIGHT + + + NNTS.TAINTED + + + NNTS.MUST + + + SV.UNBOUND_STRING_INPUT.CIN + - 489 S, 66 X, 70 X, 71 X + + 489 S, 66 X, 70 X, 71 X + Partially implemented @@ -214,11 +352,21 @@ void f(std::istream &in) { 2021.2 - CERT_CPP-STR50-b - CERT_CPP-STR50-c - CERT_CPP-STR50-e - CERT_CPP-STR50-f - CERT_CPP-STR50-g + + CERT_CPP-STR50-b + + + CERT_CPP-STR50-c + + + CERT_CPP-STR50-e + + + CERT_CPP-STR50-f + + + CERT_CPP-STR50-g + Avoid overflow due to reading a not zero terminated string @@ -244,7 +392,7 @@ void f(std::istream &in) { Checks for: - Use of dangerous standard functionse of dangerous standard function, missing null in string arrayissing null in string array, buffer overflow from incorrect string format specifieruffer overflow from incorrect string format specifier, destination buffer overflow in string manipulationestination buffer overflow in string manipulation. + Use of dangerous standard function, missing null in string array, buffer overflow from incorrect string format specifier, destination buffer overflow in string manipulation. Rule partially covered.
    - S3519 + + + S3519 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -300,7 +462,9 @@ void f(std::istream &in) { diff --git a/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert-standard.qhelp b/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert-standard.qhelp index 8ca1ca0627..63c03b5478 100644 --- a/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert-standard.qhelp +++ b/cpp/cert/src/rules/STR50-CPP/OperationMayNotNullTerminateCStyleStringCert-standard.qhelp @@ -1,50 +1,148 @@
    -

    Copying data to a buffer that is not large enough to hold that data results in a buffer overflow. Buffer overflows occur frequently when manipulating strings [Seacord 2013]. To prevent such errors, either limit copies through truncation or, preferably, ensure that the destination is of sufficient size to hold the data to be copied. C-style strings require a null character to indicate the end of the string, while the C++ std::basic_string template requires no such character.

    +

    + Copying data to a buffer that is not large enough to hold that data results in a buffer overflow. Buffer overflows occur frequently when manipulating strings [ + + Seacord 2013 + + ]. To prevent such errors, eitherย limit copies through truncation or, preferably, ensure that the destination is of sufficient size to hold the data to be copied. C-style strings require a null character to indicate the end of the string, while the C++ + + std::basic_string + + template requires no such character. +

    -

    Because the input is unbounded, the following code could lead to a buffer overflow.

    - #include <iostream> - +

    + Because the input is unbounded, the following code could lead to a buffer overflow. +

    + + #include <iostream> +ย  void f() { char buf[12]; std::cin >> buf; -} +} +
    -

    To solve this problem, it may be tempting to use the std::ios_base::width() method, but there still is a trap, as shown in this noncompliant code example.

    - #include <iostream> - +

    + To solve this problem, it may be tempting to use the + + std::ios_base::width() + + method, but there still is a trap, as shown in this noncompliant code example. +

    + + #include <iostream> +ย  void f() { char bufOne[12]; char bufTwo[12]; std::cin.width(12); std::cin >> bufOne; std::cin >> bufTwo; -} -

    In this example, the first read will not overflow, but could fill bufOne with a truncated string. Furthermore, the second read still could overflow bufTwo. The C++ Standard, [istream.extractors], paragraphs 7โ€“9 [ISO/IEC 14882-2014], describes the behavior of operator>>(basic_istream &, charT *) and, in part, states the following:

    +} +
    +

    + In this example, the first read will not overflow, but could fill + + bufOne + + with a truncated string. Furthermore, the second read still could overflow + + bufTwo + + . The C++ Standard, [istream.extractors], paragraphs 7โ€“9 ย [ + + ISO/IEC 14882-2014 + + ], describes the behavior of + + operator>>(basic_istream &, charT *) + + and, in part, states the following: +

    -

    operator>> then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted. operator>> then calls width(0).

    +

    + + operator>> + + then stores a null byte ( + + charT() + + ) in the next position, which may be the first position ifย no characters were extracted. + + operator>> + + then calls + + width(0) + + . +

    -

    Consequently, it is necessary to call width() prior to each operator>> call passing a bounded array. However, this does not account for the input being truncated, which may lead to information loss or a possible vulnerability.

    +

    + Consequently, it is necessary to call + + width() + + prior to each + + operator>> + + call passing a bounded array. However, this does not account for the input being truncated, which may lead to information loss or a possible + + vulnerability + + . +

    -

    The best solution for ensuring that data is not truncated and for guarding against buffer overflows is to use std::string instead of a bounded array, as in this compliant solution.

    - #include <iostream> +

    + The best solution for ensuring that data is not truncated and for guarding against buffer overflows is to use + + std::string + + instead of a bounded array, as in this compliant solution. +

    + + #include <iostream> #include <string> - +ย  void f() { std::string input; std::string stringOne, stringTwo; std::cin >> stringOne >> stringTwo; -} +} +
    -

    In this noncompliant example, the unformatted input function std::basic_istream<T>::read() is used to read an unformatted character array of 32 characters from the given file. However, the read() function does not guarantee that the string will be null terminated, so the subsequent call of the std::string constructor results in undefined behavior if the character array does not contain a null terminator.

    - #include <fstream> +

    + In this noncompliant example, the unformatted input function + + std::basic_istream<T>::read() + + is used to read an unformatted character array of 32 characters from the given file. However, the + + read() + + function does not guarantee that the string will be null terminated, so the subsequent call of the + + std::string + + constructor results in + + undefined behavior + + if the character array does not contain a null terminator. +

    + + #include <fstream> #include <string> - +ย  void f(std::istream &in) { char buffer[32]; try { @@ -55,11 +153,23 @@ void f(std::istream &in) { std::string str(buffer); // ... -} +} +
    -

    This compliant solution assumes that the input from the file is at most 32 characters. Instead of inserting a null terminator, it constructs the std::string object based on the number of characters read from the input stream. If the size of the input is uncertain, it is better to use std::basic_istream<T>::readsome() or a formatted input function, depending on need.

    - #include <fstream> +

    + This compliant solution assumes that the input from the file is at most 32 characters. Instead of inserting a null terminator, it constructs the + + std::string + + object based on the number of characters read from the input stream. If the size of the input is uncertain, it is better to use + + std::basic_istream<T>::readsome() + + or a formatted input function, depending on need. +

    + + #include <fstream> #include <string> void f(std::istream &in) { @@ -71,10 +181,17 @@ void f(std::istream &in) { } std::string str(buffer, in.gcount()); // ... -} +} +
    -

    Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code with the permissions of the vulnerable process.

    +

    + Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can + + exploit + + this condition to execute arbitrary code with the permissions of the vulnerable process. +

    Subclause 27.7.2.2.3, " - basic_istream::operator>> + + basic_istream::operator>> + " Subclause 27.7.2.3, "Unformatted Input Functions"
    @@ -111,10 +228,14 @@ void f(std::istream &in) { Medium @@ -144,11 +265,16 @@ void f(std::istream &in) { @@ -181,10 +309,18 @@ void f(std::istream &in) { 2021.4 @@ -198,7 +334,9 @@ void f(std::istream &in) { @@ -258,7 +406,11 @@ void f(std::istream &in) { 4.10 @@ -267,7 +419,17 @@ void f(std::istream &in) {
    - P18 + + P18 + - L1 + + L1 +
    - 6.2p0 + 6.1p0 - MISC.MEM.NTERM - LANG.MEM.BOLANG.MEM.TO + + MISC.MEM.NTERM + + + LANG.MEM.BO + LANG.MEM.TO + No space for null terminator @@ -166,7 +292,9 @@ void f(std::istream &in) { 2021.2 - C++2835, C++2836, C++2839, C++5216 + + C++2835, C++2836, C++2839, C++5216 + - NNTS.MIGHT - NNTS.TAINTED - NNTS.MUST - SV.UNBOUND_STRING_INPUT.CIN + + NNTS.MIGHT + + + NNTS.TAINTED + + + NNTS.MUST + + + SV.UNBOUND_STRING_INPUT.CIN + - 489 S, 66 X, 70 X, 71 X + + 489 S, 66 X, 70 X, 71 X + Partially implemented @@ -214,11 +352,21 @@ void f(std::istream &in) { 2021.2 - CERT_CPP-STR50-b - CERT_CPP-STR50-c - CERT_CPP-STR50-e - CERT_CPP-STR50-f - CERT_CPP-STR50-g + + CERT_CPP-STR50-b + + + CERT_CPP-STR50-c + + + CERT_CPP-STR50-e + + + CERT_CPP-STR50-f + + + CERT_CPP-STR50-g + Avoid overflow due to reading a not zero terminated string @@ -244,7 +392,7 @@ void f(std::istream &in) { Checks for: - Use of dangerous standard functionse of dangerous standard function, missing null in string arrayissing null in string array, buffer overflow from incorrect string format specifieruffer overflow from incorrect string format specifier, destination buffer overflow in string manipulationestination buffer overflow in string manipulation. + Use of dangerous standard function, missing null in string array, buffer overflow from incorrect string format specifier, destination buffer overflow in string manipulation. Rule partially covered.
    - S3519 + + + S3519 + +
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -300,7 +462,9 @@ void f(std::istream &in) { diff --git a/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer-standard.qhelp b/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer-standard.qhelp index d13f380918..f8cd589d07 100644 --- a/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer-standard.qhelp +++ b/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer-standard.qhelp @@ -1,65 +1,342 @@
    -

    The std::basic_string type uses the traits design pattern to handle implementation details of the various string types, resulting in a series of string-like classes with a common, underlying implementation. Specifically, the std::basic_string class is paired with std::char_traits to create the std::string, std::wstring, std::u16string, and std::u32string classes. The std::char_traits class is explicitly specialized to provide policy-based implementation details to the std::basic_string type. One such implementation detail is the std::char_traits::length() function, which is frequently used to determine the number of characters in a null-terminated string. According to the C++ Standard, [char.traits.require], Table 62 [ISO/IEC 14882-2014], passing a null pointer to this function is undefined behavior because it would result in dereferencing a null pointer.

    -

    The following std::basic_string member functions result in a call to std::char_traits::length():

    +

    + The + + std::basic_string + + type uses the + + traits + + design pattern to handle implementation details of the various string types, resulting in a series of string-like classes with a common, underlying implementation. Specifically, the + + std::basic_string + + class is paired with + + std::char_traits + + to create the + + std::string + + , + + std::wstring + + , + + std::u16string + + , and + + std::u32string + + classes. The + + std::char_traits + + class is explicitly specialized to provide policy-based implementation details to the + + std::basic_string + + type. One such implementation detail is the + + std::char_traits::length() + + function, which is frequently used to determine the number of characters in a null-terminated string. According to the C++ Standard, [char.traits.require], Table 62 + [ + + ISO/IEC 14882-2014 + + ] + ,ย passing a null pointer to this function is + + undefined behavior + + because it would result in dereferencing a null pointer. +

    +

    + The following + + std::basic_string + + member functions result in a call to + + std::char_traits::length() + + : +

      -
    • basic_string::basic_string(const charT *, const Allocator &)
    • -
    • basic_string &basic_string::append(const charT *)
    • -
    • basic_string &basic_string::assign(const charT *)
    • -
    • basic_string &basic_string::insert(size_type, const charT *)
    • -
    • basic_string &basic_string::replace(size_type, size_type, const charT *)
    • -
    • basic_string &basic_string::replace(const_iterator, const_iterator, const charT *)
    • -
    • size_type basic_string::find(const charT *, size_type)
    • -
    • size_type basic_string::rfind(const charT *, size_type)
    • -
    • size_type basic_string::find_first_of(const charT *, size_type)
    • -
    • size_type basic_string::find_last_of(const charT *, size_type)
    • -
    • size_type basic_string::find_first_not_of(const charT *, size_type)
    • -
    • size_type basic_string::find_last_not_of(const charT *, size_type)
    • -
    • int basic_string::compare(const charT *)
    • -
    • int basic_string::compare(size_type, size_type, const charT *)
    • -
    • basic_string &basic_string::operator=(const charT *)
    • -
    • basic_string &basic_string::operator+=(const charT *)
    • +
    • + + basic_string::basic_string(const charT *, const Allocator &) + +
    • +
    • + + basic_string &basic_string::append(const charT *) + +
    • +
    • + + basic_string &basic_string::assign(const charT *) + +
    • +
    • + + basic_string &basic_string::insert(size_type, const charT *) + +
    • +
    • + + basic_string &basic_string::replace(size_type, size_type, const charT *) + +
    • +
    • + + basic_string &basic_string::replace(const_iterator, const_iterator, const charT *) + +
    • +
    • + + size_type basic_string::find(const charT *, size_type) + +
    • +
    • + + size_type basic_string::rfind(const charT *, size_type) + +
    • +
    • + + size_type basic_string::find_first_of(const charT *, size_type) + +
    • +
    • + + size_type basic_string::find_last_of(const charT *, size_type) + +
    • +
    • + + size_type basic_string::find_first_not_of(const charT *, size_type) + +
    • +
    • + + size_type basic_string::find_last_not_of(const charT *, size_type) + +
    • +
    • + + int basic_string::compare(const charT *) + +
    • +
    • + + int basic_string::compare(size_type, size_type, const charT *) + +
    • +
    • + + basic_string &basic_string::operator=(const charT *) + +
    • +
    • + + basic_string &basic_string::operator+=(const charT *) + +
    -

    The following std::basic_string nonmember functions result in a call to to std::char_traits::length():

    +

    + The following + + std::basic_string + + nonmember functions result in a call to to + + std::char_traits::length() + + : +

      -
    • basic_string operator+(const charT *, const basic_string&)
    • -
    • basic_string operator+(const charT *, basic_string &&)
    • -
    • basic_string operator+(const basic_string &, const charT *)
    • -
    • basic_string operator+(basic_string &&, const charT *)
    • -
    • bool operator==(const charT *, const basic_string &)
    • -
    • bool operator==(const basic_string &, const charT *)
    • -
    • bool operator!=(const charT *, const basic_string &)
    • -
    • bool operator!=(const basic_string &, const charT *)
    • -
    • bool operator<(const charT *, const basic_string &)
    • -
    • bool operator<(const basic_string &, const charT *)
    • -
    • bool operator>(const charT *, const basic_string &)
    • -
    • bool operator>(const basic_string &, const charT *)
    • -
    • bool operator<=(const charT *, const basic_string &)
    • -
    • bool operator<=(const basic_string &, const charT *)
    • -
    • bool operator>=(const charT *, const basic_string &)
    • -
    • bool operator>=(const basic_string &, const charT *)
    • +
    • + + basic_string operator+(const charT *, const basic_string&) + +
    • +
    • + + basic_string operator+(const charT *, basic_string &&) + +
    • +
    • + + basic_string operator+(const basic_string &, const charT *) + +
    • +
    • + + basic_string operator+(basic_string &&, const charT *) + +
    • +
    • + + bool operator==(const charT *, const basic_string &) + +
    • +
    • + + bool operator==(const basic_string &, const charT *) + +
    • +
    • + + bool operator!=(const charT *, const basic_string &) + +
    • +
    • + + bool operator!=(const basic_string &, const charT *) + +
    • +
    • + + bool operator<(const charT *, const basic_string &) + +
    • +
    • + + bool operator<(const basic_string &, const charT *) + +
    • +
    • + + bool operator>(const charT *, const basic_string &) + +
    • +
    • + + bool operator>(const basic_string &, const charT *) + +
    • +
    • + + bool operator<=(const charT *, const basic_string &) + +
    • +
    • + + bool operator<=(const basic_string &, const charT *) + +
    • +
    • + + bool operator>=(const charT *, const basic_string &) + +
    • +
    • + + bool operator>=(const basic_string &, const charT *) + +
    -

    Do not call any of the preceding functions with a null pointer as the const charT * argument.

    -

    This rule is a specific instance of EXP34-C. Do not dereference null pointers.

    -

    Implementation Details

    -

    Some standard library vendors, such as libstdc++, throw a std::logic_error when a null pointer is used in the above function calls, though not when calling std::char_traits::length(). However, std::logic_error is not a requirement of the C++ Standard, and some vendors (e.g., libc++ and the Microsoft Visual Studio STL) do not implement this behavior. For portability, you should not rely on this behavior.

    +

    + Do not call any of the preceding functions with a null pointer as the + + const charT * + + argument. +

    +

    + This rule is a specific instance of + + EXP34-C. Do not dereference null pointers + + . +

    +

    + + Implementation Details + +

    +

    + Some standard library vendors, such as + + libstdc++, + + throw a + + std::logic_error + + when a null pointer is used in the above function calls, though not when calling + + std::char_traits::length() + + . However, + + std::logic_error + + is not a requirement of the C++ Standard, and some vendors (e.g., + + libc++ + + and the + + Microsoft Visual Studio STL + + ) do not implement this behavior. For portability, you should not rely on this behavior. +

    -

    In this noncompliant code example, a std::string object is created from the results of a call to std::getenv(). However, because std::getenv() returns a null pointer on failure, this code can lead to undefined behavior when the environment variable does not exist (or some other error occurs).

    - #include <cstdlib> +

    + In this noncompliant code example, a + + std::string + + object is created from the results of a call to + + std::getenv() + + . However, because + + std::getenv() + + returns a null pointer on failure, this code can lead to + + undefined behavior + + when the environment variable does not exist (or some other error occurs). +

    + + #include <cstdlib> #include <string> - +ย  void f() { std::string tmp(std::getenv("TMP")); if (!tmp.empty()) { // ... } -} +} +
    -

    In this compliant solution, the results from the call to std::getenv() are checked for null before the std::string object is constructed.

    - #include <cstdlib> +

    + In this compliant solution, the results from the call to + + std::getenv() + + are checked for null before the + + std::string + + object is constructed. +

    + + #include <cstdlib> #include <string> void f() { @@ -68,10 +345,33 @@ void f() { if (!tmp.empty()) { // ... } -} +} +
    -

    Dereferencing a null pointer is undefined behavior, typically abnormal program termination. In some situations, however, dereferencing a null pointer can lead to the execution of arbitrary code [Jack 2007, van Sprundel 2006]. The indicated severity is for this more severe case; on platforms where it is not possible to exploit a null pointer dereference to execute arbitrary code, the actual severity is low.

    +

    + Dereferencing a null pointer is + + undefined behavior + + , typically + + abnormal program termination + + . In some situations, however, dereferencing a null pointer can lead to the execution of arbitrary code [ + + Jack 2007 + + , + + van Sprundel 2006 + + ]. The indicated severity is for this more severe case; on platforms where it is not possible to + + exploit + + a null pointer dereference to execute arbitrary code, the actual severity is low. +

    Subclause 27.7.2.2.3, " - basic_istream::operator>> + + basic_istream::operator>> + " Subclause 27.7.2.3, "Unformatted Input Functions"
    @@ -108,10 +408,14 @@ void f() { Medium @@ -144,7 +448,9 @@ void f() { 20.10 @@ -159,7 +465,9 @@ void f() { 2021.2 @@ -174,18 +482,81 @@ void f() { 2021.4 @@ -200,7 +571,9 @@ void f() { 2021.2
    - P18 + + P18 + - L1 + + L1 +
    - assert_failure + + assert_failure + - C++4770, C++4771, C++4772, C++4773, C++4774 + + C++4770, C++4771, C++4772, C++4773, C++4774 + - NPD.CHECK.CALL.MIGHT - NPD.CHECK.CALL.MUST - NPD.CHECK.MIGHT - NPD.CHECK.MUST - NPD.CONST.CALL - NPD.CONST.DEREF - NPD.FUNC.CALL.MIGHT - NPD.FUNC.CALL.MUST - NPD.FUNC.MIGHT - NPD.FUNC.MUST - NPD.GEN.CALL.MIGHTNPD.GEN.CALL.MUSTNPD.GEN.MIGHTNPD.GEN.MUST - RNPD.CALLRNPD.DEREF + + + NPD.CHECK.CALL.MIGHT + + + + + NPD.CHECK.CALL.MUST + + + + + NPD.CHECK.MIGHT + + + + + NPD.CHECK.MUST + + + + + NPD.CONST.CALL + + + + + NPD.CONST.DEREF + + + + + NPD.FUNC.CALL.MIGHT + + + + + NPD.FUNC.CALL.MUST + + + + + NPD.FUNC.MIGHT + + + + + NPD.FUNC.MUST + + + + + NPD.GEN.CALL.MIGHT + + + NPD.GEN.CALL.MUST + + + NPD.GEN.MIGHT + + + NPD.GEN. + + + MUST + + + + + RNPD.CALL + + + RNPD.DEREF + + - CERT_CPP-STR51-a + + CERT_CPP-STR51-a + Avoid null pointer dereferencing @@ -210,7 +583,17 @@ void f() {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    diff --git a/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql b/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql index e775dc205f..99c243f234 100644 --- a/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql +++ b/cpp/cert/src/rules/STR51-CPP/DoNotAttemptToCreateAStringFromANullPointer.ql @@ -7,6 +7,7 @@ * @problem.severity error * @tags external/cert/id/str51-cpp * correctness + * external/cert/default-disabled * external/cert/obligation/rule */ diff --git a/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString-standard.qhelp b/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString-standard.qhelp index b437ef3527..ad6cf14210 100644 --- a/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString-standard.qhelp +++ b/cpp/cert/src/rules/STR52-CPP/UseValidReferencesForElementsOfString-standard.qhelp @@ -1,20 +1,144 @@
    -

    Since std::basic_string is a container of characters, this rule is a specific instance of CTR51-CPP. Use valid references, pointers, and iterators to reference elements of a container. As a container, it supports iterators just like other containers in the Standard Template Library. However, the std::basic_string template class has unusual invalidation semantics. The C++ Standard, [string.require], paragraph 5 [ISO/IEC 14882-2014], states the following:

    +

    + Since + + std::basic_string + + is a container of characters, this rule is a specific instance of + + CTR51-CPP. Use valid references, pointers, and iterators to reference elements of a container + + . As a container, it supports iterators just like other containers in the Standard Template Library. However, the + + std::basic_string + + template class has unusual invalidation semantics. The C++ Standard,ย [string.require], paragraph 5 [ + + ISO/IEC 14882-2014 + + ], states the following: +

    -

    References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:

    +

    + References, pointers, and iterators referring to the elements of a + + basic_string + + sequence may be invalidatedย by the following uses of that + + basic_string + + object: +

      -
    • As an argument to any standard library function taking a reference to non-const basic_string as an argument.
    • -
    • Calling non-const member functions, except operator[], at, front, back, begin, rbegin, end, and rend.
    • +
    • + As an argument to any standard library function taking a reference to non-const + + basic_string + + as anย argument. +
    • +
    • + Calling non-const member functions, except + + operator[] + + , + + at + + , + + front + + , + + back + + , + + begin + + , + + rbegin + + , + + end + + , and + + rend + + . +
    -

    Examples of standard library functions taking a reference to non-const std::basic_string are std::swap(), ::operator>>(basic_istream &, string &), and std::getline().

    -

    Do not use an invalidated reference, pointer, or iterator because doing so results in undefined behavior.

    -

    Noncompliant Code Example

    -

    This noncompliant code example copies input into a std::string, replacing semicolon (;) characters with spaces. This example is noncompliant because the iterator loc is invalidated after the first call to insert(). The behavior of subsequent calls to insert() is undefined.

    - #include <string> - +

    + Examples of standard library functions taking a reference to non- + + const + + + std::basic_string + + are + + std::swap() + + , + + ::operator>>(basic_istream &, string &) + + , and + + std::getline() + + . +

    +

    + Do not use an invalidated reference, pointer, or iterator because doing so results in + + undefined behavior + + . +

    +

    + Noncompliant Code Example +

    +

    + This noncompliant code example copies + + input + + into a + + std::string + + , replacing semicolon ( + + ;) + + characters with spaces. This example is noncompliant because the iterator + + loc + + is invalidated after the first call to + + insert() + + . The behavior of subsequent calls to + + insert() + + is undefined. +

    + + #include <string> +ย  void f(const std::string &input) { std::string email; @@ -23,11 +147,23 @@ void f(const std::string &input) { for (auto i = input.begin(), e = input.end(); i != e; ++i, ++loc) { email.insert(loc, *i != ';' ? *i : ' '); } -} +} +
    -

    In this compliant solution, the value of the iterator loc is updated as a result of each call to insert() so that the invalidated iterator is never accessed. The updated iterator is then incremented at the end of the loop.

    - #include <string> +

    + In this compliant solution, the value of the iterator + + loc + + is updated as a result of each call to + + insert() + + so that the invalidated iterator is never accessed. The updated iterator is then incremented at the end of the loop. +

    + + #include <string> void f(const std::string &input) { std::string email; @@ -38,36 +174,67 @@ void f(const std::string &input) { loc = email.insert(loc, *i != ';' ? *i : ' '); } } - +
    -

    This compliant solution uses a standard algorithm to perform the replacement. When possible, using a generic algorithm is preferable to inventing your own solution.

    - #include <algorithm> +

    + This compliant solution uses a standard algorithm to perform the replacement. When possible, using a generic algorithm is preferable to inventing your own solution. +

    + + #include <algorithm> #include <string> void f(const std::string &input) { std::string email{input}; std::replace(email.begin(), email.end(), ';', ' '); -} +} +
    -

    In this noncompliant code example, data is invalidated after the call to replace(), and so its use in g() is undefined behavior.

    - #include <iostream> +

    + In this noncompliant code example, + + data + + is invalidated after the call to + + replace() + + , and so its use in + + g() + + is undefined behavior. +

    + + #include <iostream> #include <string> - +ย  extern void g(const char *); - +ย  void f(std::string &exampleString) { const char *data = exampleString.data(); // ... exampleString.replace(0, 2, "bb"); // ... g(data); -} +} +
    -

    In this compliant solution, the pointer to exampleString's internal buffer is not generated until after the modification from replace() has completed.

    - #include <iostream> +

    + In this compliant solution, the pointer to + + exampleString + + 's internal buffer is not generated until after the modification from + + replace() + + has completed. +

    + + #include <iostream> #include <string> extern void g(const char *); @@ -77,10 +244,13 @@ void f(std::string &exampleString) { exampleString.replace(0, 2, "bb"); // ... g(exampleString.data()); -} +} +
    -

    Using an invalid reference, pointer, or iterator to a string object could allow an attacker to run arbitrary code.

    +

    + Using an invalid reference, pointer, or iterator to a string object could allow an attacker to run arbitrary code. +

    @@ -117,10 +287,14 @@ void f(std::string &exampleString) { High @@ -143,22 +317,6 @@ void f(std::string &exampleString) { Description - - - - - - @@ -184,7 +344,9 @@ void f(std::string &exampleString) { 2021.2
    - P6 + + P6 + - L2 + + L2 +
    - - CodeSonar - - - 6.2p0 - - ALLOC.UAF - - Use After Free -
    @@ -169,7 +327,9 @@ void f(std::string &exampleString) { 2021.2 - C++4746, C++4747, C++4748, C++4749 + + C++4746, C++4747, C++4748, C++4749 + - CERT_CPP-STR52-a + + CERT_CPP-STR52-a + Use valid references, pointers, and iterators to reference elements of a basic_string @@ -194,7 +356,17 @@ void f(std::string &exampleString) {
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -227,7 +399,9 @@ void f(std::string &exampleString) { diff --git a/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess-standard.qhelp b/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess-standard.qhelp index dc0c2c8df7..b55203807b 100644 --- a/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess-standard.qhelp +++ b/cpp/cert/src/rules/STR53-CPP/RangeCheckStringElementAccess-standard.qhelp @@ -1,24 +1,120 @@
    -

    The std::string index operators const_reference operator[](size_type) const and reference operator[](size_type) return the character stored at the specified position, pos. When pos >= size(), a reference to an object of type charT with value charT() is returned. The index operators are unchecked (no exceptions are thrown for range errors), and attempting to modify the resulting out-of-range object results in undefined behavior.

    -

    Similarly, the std::string::back() and std::string::front() functions are unchecked as they are defined to call through to the appropriate operator[]() without throwing.

    -

    Do not pass an out-of-range value as an argument to std::string::operator[](). Similarly, do not call std::string::back() or std::string::front() on an empty string. This rule is a specific instance of CTR50-CPP. Guarantee that container indices and iterators are within the valid range.

    +

    + The + + std::string + + index operators + + const_reference operator[](size_type) const + + and + + reference operator[](size_type) + + return the character stored at the specified position, + + pos + + . When + + pos >= size() + + , a reference to an object of type + + charT + + with value + + charT() + + is returned. The index operators are unchecked (no exceptions are thrown for range errors), and attempting to modify the resulting out-of-range object results in + + undefined behavior + + . +

    +

    + Similarly, the + + std::string::back() + + and + + std::string::front() + + functions are unchecked as they are defined to call through to the appropriate + + operator[]() + + without throwing. +

    +

    + Do not pass an out-of-range value as an argument to + + std::string::operator[]() + + . Similarly, do not call + + std::string::back() + + or + + std::string::front() + + on an empty string. This rule is a specific instance of + + CTR50-CPP. Guarantee that container indices and iterators are within the valid range + + . +

    -

    In this noncompliant code example, the value returned by the call to get_index() may be greater than the number of elements stored in the string, resulting in undefined behavior.

    - #include <string> - +

    + In this noncompliant code example, the value returned by the call to + + get_index() + + may be greater than the number of elements stored in the string, resulting in + + undefined behavior + + . +

    + + #include <string> +ย  extern std::size_t get_index(); - +ย  void f() { std::string s("01234567"); s[get_index()] = '1'; -} +} +
    -

    This compliant solution uses the std::basic_string::at() function, which behaves in a similar fashion to the index operator[] but throws a std::out_of_range exception if pos >= size().

    - #include <stdexcept> +

    + This compliant solution uses the + + std::basic_string::at() + + function, which behaves in a similar fashion to the index + + operator[] + + but throws a + + std::out_of_range + + exception if + + pos >= size(). + +

    + + #include <stdexcept> #include <string> extern std::size_t get_index(); @@ -29,11 +125,22 @@ void f() { } catch (std::out_of_range &) { // Handle error } -} +} +
    -

    This compliant solution checks that the value returned by get_index() is within a valid range before calling operator[]().

    - #include <string> +

    + This compliant solution checks that the value returned by + + get_index() + + is within a valid range before calling + + operator[](). + +

    + + #include <string> extern std::size_t get_index(); @@ -45,21 +152,37 @@ void f() { } else { // Handle error } -} +} +
    -

    This noncompliant code example attempts to replace the initial character in the string with a capitalized equivalent. However, if the given string is empty, the behavior is undefined.

    - #include <string> +

    + This noncompliant code example attempts to replace the initial character in the string with a capitalized equivalent. However, if the given string is empty, the behavior is + + undefined + + . +

    + + #include <string> #include <locale> void capitalize(std::string &s) { std::locale loc; s.front() = std::use_facet<std::ctype<char>>(loc).toupper(s.front()); -} +} +
    -

    In this compliant solution, the call to std::string::front() is made only if the string is not empty.

    - #include <string> +

    + In this compliant solution, the call to + + std::string::front() + + is made only if the string is not empty. +

    + + #include <string> #include <locale> void capitalize(std::string &s) { @@ -69,10 +192,17 @@ void capitalize(std::string &s) { std::locale loc; s.front() = std::use_facet<std::ctype<char>>(loc).toupper(s.front()); -} +} +
    -

    Unchecked element access can lead to out-of-bound reads and writes and write-anywhere exploits. These exploits can, in turn, lead to the execution of arbitrary code with the permissions of the vulnerable process.

    +

    + Unchecked element access can lead to out-of-bound reads and writes and write-anywhere + + exploits + + . These exploits can, in turn, lead to the execution of arbitrary code with the permissions of the vulnerable process. +

    Subclause 21.4.1, " - basic_string + + basic_string + General Requirements"
    @@ -109,10 +239,14 @@ void capitalize(std::string &s) { Medium @@ -145,7 +279,9 @@ void capitalize(std::string &s) { 20.10 @@ -157,14 +293,24 @@ void capitalize(std::string &s) { @@ -199,7 +347,9 @@ void capitalize(std::string &s) { 2021.2 @@ -229,7 +379,17 @@ void capitalize(std::string &s) {
    - P6 + + P6 + - L2 + + L2 +
    - assert_failure + + assert_failure + - 6.2p0 + 6.1p0 - LANG.MEM.BO - LANG.MEM.BU - LANG.MEM.TBA - LANG.MEM.TO - LANG.MEM.TU + + LANG.MEM.BO + + + LANG.MEM.BU + + + LANG.MEM.TBA + + + LANG.MEM.TO + + + LANG.MEM.TU + Buffer overrun @@ -184,7 +330,9 @@ void capitalize(std::string &s) { 2021.2 - C++3162, C++3163, C++3164, C++3165 + + C++3162, C++3163, C++3164, C++3165 + - CERT_CPP-STR53-a + + CERT_CPP-STR53-a + Guarantee that container indices are within the valid range @@ -221,7 +371,7 @@ void capitalize(std::string &s) { Checks for: - Array access out of boundsrray access out of bounds, array access with tainted indexrray access with tainted index, pointer dereference with tainted offsetointer dereference with tainted offset. + Array access out of bounds, array access with tainted index, pointer dereference with tainted offset. Rule partially covered.
    -

    Search for vulnerabilities resulting from the violation of this rule on the CERT website.

    +

    + Search for + + vulnerabilities + + resulting from the violation of this rule on the + + CERT website + + . +

    @@ -262,7 +422,9 @@ void capitalize(std::string &s) { diff --git a/cpp/cert/test/qlpack.yml b/cpp/cert/test/qlpack.yml index a2aeead468..adf42df072 100644 --- a/cpp/cert/test/qlpack.yml +++ b/cpp/cert/test/qlpack.yml @@ -1,4 +1,4 @@ name: cert-cpp-coding-standards-tests -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: cert-cpp-coding-standards extractor: cpp diff --git a/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll b/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll new file mode 100644 index 0000000000..6b8786fa58 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/ReadErrorsAndEOF.qll @@ -0,0 +1,117 @@ +import cpp +import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.standardlibrary.FileAccess + +/** + * any call to function `feof()` or `ferror()` + */ +abstract class FeofFerrorCall extends FunctionCall { } + +class FeofCall extends FeofFerrorCall { + FeofCall() { this.getTarget().hasGlobalName("feof") } +} + +class FerrorCall extends FeofFerrorCall { + FerrorCall() { this.getTarget().hasGlobalName("ferror") } +} + +pragma[inline] +predicate accessSameTarget(VariableAccess va1, VariableAccess va2) { + va1.getTarget() = va2.getTarget() +} + +predicate isShortCircuitedEdge(ControlFlowNode fst, ControlFlowNode snd) { + fst = any(LogicalAndExpr andOp).getLeftOperand() and snd = fst.getAFalseSuccessor() + or + fst = any(LogicalOrExpr orOp).getLeftOperand() and snd = fst.getATrueSuccessor() +} + +// Nodes following a file read before a call to `feof/ferror` is performed +ControlFlowNode feofUnchecked(InBandErrorReadFunctionCall read) { + result = read + or + exists(ControlFlowNode mid | + mid = feofUnchecked(read) and + //do not traverse the short-circuited CFG edge + not isShortCircuitedEdge(mid, result) and + result = mid.getASuccessor() and + //Stop recursion on call to feof/ferror on the correct file + not accessSameTarget(result.(FeofCall).getArgument(0), read.getFileExpr()) + ) +} + +// Nodes following a file read before a call to `feof` is performed +ControlFlowNode ferrorUnchecked(InBandErrorReadFunctionCall read) { + result = read + or + exists(ControlFlowNode mid | + mid = ferrorUnchecked(read) and + //do not traverse the short-circuited CFG edge + not isShortCircuitedEdge(mid, result) and + result = mid.getASuccessor() and + //Stop recursion on call to ferror on the correct file + not accessSameTarget(result.(FerrorCall).getArgument(0), read.getFileExpr()) + ) +} + +// No feof() or ferror() checks are performed after the function reads from a file +predicate missingFeofFerrorChecks(InBandErrorReadFunctionCall read) { + read.getEnclosingFunction() = feofUnchecked(read) + or + read.getEnclosingFunction() = ferrorUnchecked(read) +} + +abstract class EOFWEOFInvocation extends MacroInvocation { + abstract Type getRequiredType(); +} + +class EOFInvocation extends EOFWEOFInvocation { + EOFInvocation() { this.getMacroName() = "EOF" } + + override Type getRequiredType() { result instanceof IntType } +} + +class WEOFInvocation extends EOFWEOFInvocation { + WEOFInvocation() { this.getMacroName() = "WEOF" } + + override Type getRequiredType() { result instanceof Wint_t } +} + +// The equality operation `eq` checks a char fetched from `read` against a macro +predicate isMacroCheck(EqualityOperation eq, InBandErrorReadFunctionCall read) { + exists(Expr c, EOFWEOFInvocation mi | + // one operand is the char c fetched from `read` + c = eq.getAnOperand() and + DataFlow::localExprFlow(read, c) and + // c is of the appropriate type `int`/`wint_t` + c.getType() = mi.getRequiredType() and + // an operand is an invocation of the EOF macro + mi.getAGeneratedElement() = eq.getAnOperand() + ) +} + +// Nodes following a file read before a EOF/WEOF macro is checked +ControlFlowNode macroUnchecked(InBandErrorReadFunctionCall read) { + result = read.getASuccessor() + or + exists(ControlFlowNode mid | + mid = macroUnchecked(read) and + //do not traverse the short-circuited CFG edge + not isShortCircuitedEdge(mid, result) and + result = mid.getASuccessor() and + // Stop recursion on a correct comparison of the fetched char against EOF/WEOF + not isMacroCheck(result, read) + ) +} + +// No checks for comparison to EOF/WEOF are performed after the function reads from a file +predicate missingEOFWEOFChecks(InBandErrorReadFunctionCall read) { + // no comparison against EOF along one path + read.getEnclosingFunction() = macroUnchecked(read) + or + // another char is read before the comparison to EOF + exists(FileReadFunctionCall fc | + macroUnchecked(read) = fc and + accessSameTarget(read.getFileExpr(), fc.getFileExpr()) + ) +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/RuleMetadata.qll index 4f5d28032c..d6511f61b5 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/RuleMetadata.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/RuleMetadata.qll @@ -1,164 +1,21 @@ import cpp -import Allocations -import Concurrency -import Const -import Conditionals -import Functions -import BannedFunctions -import BannedLibraries -import BannedTypes -import BannedSyntax -import Classes -import Comments -import DeadCode -import Declarations -import Exceptions1 -import Exceptions2 -import ExceptionSafety -import Expressions -import Freed -import Includes -import Inheritance -import Initialization -import IntegerConversion -import Invariants -import IO -import Iterators -import Lambdas -import Literals -import Loops -import Macros -import MoveForward -import Naming -import Null -import Operators -import OperatorInvariants -import OrderOfEvaluation -import OutOfBounds -import Pointers -import Representation -import Scope -import SideEffects1 -import SideEffects2 -import SmartPointers1 -import SmartPointers2 -import Strings -import Templates -import Toolchain -import TrustBoundaries -import TypeRanges -import Uninitialized -import VirtualFunctions +private import cpp.RuleMetadata as CPPRuleMetadata +private import c.RuleMetadata as CRuleMetadata newtype TQuery = - TAllocationsPackageQuery(AllocationsQuery a) or - TClassesPackageQuery(ClassesQuery cl) or - TConcurrencyPackageQuery(ConcurrencyQuery c) or - TConditionalsPackageQuery(ConditionalsQuery cq) or - TConstPackageQuery(ConstQuery co) or - TFunctionsPackageQuery(FunctionsQuery f) or - TBannedFunctionsPackageQuery(BannedFunctionsQuery bf) or - TBannedLibrariesPackageQuery(BannedLibrariesQuery bl) or - TBannedSyntaxPackageQuery(BannedSyntaxQuery bs) or - TBannedTypesPackageQuery(BannedTypesQuery bt) or - TCommentsPackageQuery(CommentsQuery c) or - TDeadCodePackageQuery(DeadCodeQuery dc) or - TDeclarationsPackageQuery(DeclarationsQuery d) or - TExceptions1PackageQuery(Exceptions1Query e1) or - TExceptions2PackageQuery(Exceptions2Query e2) or - TExceptionSafetyPackageQuery(ExceptionSafetyQuery es) or - TExpressionsPackageQuery(ExpressionsQuery e) or - TFreedPackageQuery(FreedQuery f) or - TIncludesPackageQuery(IncludesQuery i) or - TInheritancePackageQuery(InheritanceQuery i) or - TInitializationPackageQuery(InitializationQuery init) or - TIntegerConversionPackageQuery(IntegerConversionQuery ic) or - TInvariantsPackageQuery(InvariantsQuery i) or - TIOPackageQuery(IOQuery io) or - TIteratorsPackageQuery(IteratorsQuery iter) or - TLambdasPackageQuery(LambdasQuery lambda) or - TLiteralsPackageQuery(LiteralsQuery l) or - TLoopsPackageQuery(LoopsQuery loop) or - TMacrosPackageQuery(MacrosQuery m) or - TMoveForwardPackageQuery(MoveForwardQuery mv) or - TNamingPackageQuery(NamingQuery n) or - TNullPackageQuery(NullQuery null) or - TOperatorsPackageQuery(OperatorsQuery o) or - TOperatorInvariantsPackageQuery(OperatorInvariantsQuery oi) or - TOrderOfEvaluationPackageQuery(OrderOfEvaluationQuery oe) or - TOutOfBoundsPackageQuery(OutOfBoundsQuery oob) or - TPointersPackageQuery(PointersQuery pt) or - TRepresentationPackageQuery(RepresentationQuery r) or - TScopePackageQuery(ScopeQuery sc) or - TSideEffects1PackageQuery(SideEffects1Query se1) or - TSideEffects2PackageQuery(SideEffects2Query se2) or - TSmartPointers1PackageQuery(SmartPointers1Query sp1) or - TSmartPointers2PackageQuery(SmartPointers2Query sp2) or - TStringsPackageQuery(StringsQuery st) or - TTemplatesPackageQuery(TemplatesQuery t) or - TToolchainPackageQuery(ToolchainQuery tc) or - TTrustBoundariesPackageQuery(TrustBoundariesQuery tb) or - TTypeRangesPackageQuery(TypeRangesQuery tr) or - TUninitializedPackageQuery(UninitializedQuery uinit) or - TVirtualFunctionsPackageQuery(VirtualFunctionsQuery vf) + TQueryCPP(CPPRuleMetadata::TCPPQuery t) or + TQueryC(CRuleMetadata::TCQuery t) class Query extends TQuery { - string getQueryId() { isQueryMetadata(this, result, _) } + string getQueryId() { + CPPRuleMetadata::isQueryMetadata(this, result, _) or + CRuleMetadata::isQueryMetadata(this, result, _) + } - string getRuleId() { isQueryMetadata(this, _, result) } + string getRuleId() { + CPPRuleMetadata::isQueryMetadata(this, _, result) or + CRuleMetadata::isQueryMetadata(this, _, result) + } string toString() { result = getQueryId() } } - -private predicate isQueryMetadata(Query query, string queryId, string ruleId) { - isAllocationsQueryMetadata(query, queryId, ruleId) or - isClassesQueryMetadata(query, queryId, ruleId) or - isConcurrencyQueryMetadata(query, queryId, ruleId) or - isConditionalsQueryMetadata(query, queryId, ruleId) or - isConstQueryMetadata(query, queryId, ruleId) or - isFunctionsQueryMetadata(query, queryId, ruleId) or - isBannedFunctionsQueryMetadata(query, queryId, ruleId) or - isBannedLibrariesQueryMetadata(query, queryId, ruleId) or - isBannedSyntaxQueryMetadata(query, queryId, ruleId) or - isBannedTypesQueryMetadata(query, queryId, ruleId) or - isCommentsQueryMetadata(query, queryId, ruleId) or - isDeadCodeQueryMetadata(query, queryId, ruleId) or - isDeclarationsQueryMetadata(query, queryId, ruleId) or - isExceptions1QueryMetadata(query, queryId, ruleId) or - isExceptions2QueryMetadata(query, queryId, ruleId) or - isExceptionSafetyQueryMetadata(query, queryId, ruleId) or - isExpressionsQueryMetadata(query, queryId, ruleId) or - isFreedQueryMetadata(query, queryId, ruleId) or - isIncludesQueryMetadata(query, queryId, ruleId) or - isInheritanceQueryMetadata(query, queryId, ruleId) or - isInitializationQueryMetadata(query, queryId, ruleId) or - isIntegerConversionQueryMetadata(query, queryId, ruleId) or - isInvariantsQueryMetadata(query, queryId, ruleId) or - isIOQueryMetadata(query, queryId, ruleId) or - isIteratorsQueryMetadata(query, queryId, ruleId) or - isLambdasQueryMetadata(query, queryId, ruleId) or - isLiteralsQueryMetadata(query, queryId, ruleId) or - isLoopsQueryMetadata(query, queryId, ruleId) or - isMacrosQueryMetadata(query, queryId, ruleId) or - isMoveForwardQueryMetadata(query, queryId, ruleId) or - isNamingQueryMetadata(query, queryId, ruleId) or - isNullQueryMetadata(query, queryId, ruleId) or - isOperatorsQueryMetadata(query, queryId, ruleId) or - isOperatorInvariantsQueryMetadata(query, queryId, ruleId) or - isOrderOfEvaluationQueryMetadata(query, queryId, ruleId) or - isOutOfBoundsQueryMetadata(query, queryId, ruleId) or - isPointersQueryMetadata(query, queryId, ruleId) or - isRepresentationQueryMetadata(query, queryId, ruleId) or - isScopeQueryMetadata(query, queryId, ruleId) or - isSideEffects1QueryMetadata(query, queryId, ruleId) or - isSideEffects2QueryMetadata(query, queryId, ruleId) or - isSmartPointers1QueryMetadata(query, queryId, ruleId) or - isSmartPointers2QueryMetadata(query, queryId, ruleId) or - isStringsQueryMetadata(query, queryId, ruleId) or - isTemplatesQueryMetadata(query, queryId, ruleId) or - isToolchainQueryMetadata(query, queryId, ruleId) or - isTrustBoundariesQueryMetadata(query, queryId, ruleId) or - isTypeRangesQueryMetadata(query, queryId, ruleId) or - isUninitializedQueryMetadata(query, queryId, ruleId) or - isVirtualFunctionsQueryMetadata(query, queryId, ruleId) -} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/IO1.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/IO1.qll new file mode 100644 index 0000000000..f0aa85cd8a --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/IO1.qll @@ -0,0 +1,122 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype IO1Query = + TExcludeUserInputFromFormatStringsQuery() or + TDistinguishBetweenCharReadFromAFileAndEofOrWeofQuery() or + TEndOfFileCheckPortabilityQuery() or + TDoNotAlternatelyIOFromAStreamWithoutPositioningQuery() or + TCloseFilesWhenTheyAreNoLongerNeededQuery() or + TUndefinedBehaviorAccessingAClosedFileQuery() or + TFileUsedAfterClosedQuery() + +predicate isIO1QueryMetadata(Query query, string queryId, string ruleId) { + query = + // `Query` instance for the `excludeUserInputFromFormatStrings` query + IO1Package::excludeUserInputFromFormatStringsQuery() and + queryId = + // `@id` for the `excludeUserInputFromFormatStrings` query + "c/cert/exclude-user-input-from-format-strings" and + ruleId = "FIO30-C" + or + query = + // `Query` instance for the `distinguishBetweenCharReadFromAFileAndEofOrWeof` query + IO1Package::distinguishBetweenCharReadFromAFileAndEofOrWeofQuery() and + queryId = + // `@id` for the `distinguishBetweenCharReadFromAFileAndEofOrWeof` query + "c/cert/distinguish-between-char-read-from-a-file-and-eof-or-weof" and + ruleId = "FIO34-C" + or + query = + // `Query` instance for the `endOfFileCheckPortability` query + IO1Package::endOfFileCheckPortabilityQuery() and + queryId = + // `@id` for the `endOfFileCheckPortability` query + "c/cert/end-of-file-check-portability" and + ruleId = "FIO34-C" + or + query = + // `Query` instance for the `doNotAlternatelyIOFromAStreamWithoutPositioning` query + IO1Package::doNotAlternatelyIOFromAStreamWithoutPositioningQuery() and + queryId = + // `@id` for the `doNotAlternatelyIOFromAStreamWithoutPositioning` query + "c/cert/do-not-alternately-io-from-a-stream-without-positioning" and + ruleId = "FIO39-C" + or + query = + // `Query` instance for the `closeFilesWhenTheyAreNoLongerNeeded` query + IO1Package::closeFilesWhenTheyAreNoLongerNeededQuery() and + queryId = + // `@id` for the `closeFilesWhenTheyAreNoLongerNeeded` query + "c/cert/close-files-when-they-are-no-longer-needed" and + ruleId = "FIO42-C" + or + query = + // `Query` instance for the `undefinedBehaviorAccessingAClosedFile` query + IO1Package::undefinedBehaviorAccessingAClosedFileQuery() and + queryId = + // `@id` for the `undefinedBehaviorAccessingAClosedFile` query + "c/cert/undefined-behavior-accessing-a-closed-file" and + ruleId = "FIO46-C" + or + query = + // `Query` instance for the `fileUsedAfterClosed` query + IO1Package::fileUsedAfterClosedQuery() and + queryId = + // `@id` for the `fileUsedAfterClosed` query + "c/misra/file-used-after-closed" and + ruleId = "RULE-22-6" +} + +module IO1Package { + Query excludeUserInputFromFormatStringsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `excludeUserInputFromFormatStrings` query + TQueryC(TIO1PackageQuery(TExcludeUserInputFromFormatStringsQuery())) + } + + Query distinguishBetweenCharReadFromAFileAndEofOrWeofQuery() { + //autogenerate `Query` type + result = + // `Query` type for `distinguishBetweenCharReadFromAFileAndEofOrWeof` query + TQueryC(TIO1PackageQuery(TDistinguishBetweenCharReadFromAFileAndEofOrWeofQuery())) + } + + Query endOfFileCheckPortabilityQuery() { + //autogenerate `Query` type + result = + // `Query` type for `endOfFileCheckPortability` query + TQueryC(TIO1PackageQuery(TEndOfFileCheckPortabilityQuery())) + } + + Query doNotAlternatelyIOFromAStreamWithoutPositioningQuery() { + //autogenerate `Query` type + result = + // `Query` type for `doNotAlternatelyIOFromAStreamWithoutPositioning` query + TQueryC(TIO1PackageQuery(TDoNotAlternatelyIOFromAStreamWithoutPositioningQuery())) + } + + Query closeFilesWhenTheyAreNoLongerNeededQuery() { + //autogenerate `Query` type + result = + // `Query` type for `closeFilesWhenTheyAreNoLongerNeeded` query + TQueryC(TIO1PackageQuery(TCloseFilesWhenTheyAreNoLongerNeededQuery())) + } + + Query undefinedBehaviorAccessingAClosedFileQuery() { + //autogenerate `Query` type + result = + // `Query` type for `undefinedBehaviorAccessingAClosedFile` query + TQueryC(TIO1PackageQuery(TUndefinedBehaviorAccessingAClosedFileQuery())) + } + + Query fileUsedAfterClosedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `fileUsedAfterClosed` query + TQueryC(TIO1PackageQuery(TFileUsedAfterClosedQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor1.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor1.qll new file mode 100644 index 0000000000..7037c9f195 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/Preprocessor1.qll @@ -0,0 +1,74 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata + +newtype Preprocessor1Query = + TIncludeDirectivesPrecededByDirectivesOrCommentsQuery() or + TPreprocessorHashOperatorsShouldNotBeUsedQuery() or + TForbiddenCharactersInHeaderFileNameQuery() or + TIdentifiersUsedInPreprocessorExpressionQuery() + +predicate isPreprocessor1QueryMetadata(Query query, string queryId, string ruleId) { + query = + // `Query` instance for the `includeDirectivesPrecededByDirectivesOrComments` query + Preprocessor1Package::includeDirectivesPrecededByDirectivesOrCommentsQuery() and + queryId = + // `@id` for the `includeDirectivesPrecededByDirectivesOrComments` query + "c/misra/include-directives-preceded-by-directives-or-comments" and + ruleId = "RULE-20-1" + or + query = + // `Query` instance for the `preprocessorHashOperatorsShouldNotBeUsed` query + Preprocessor1Package::preprocessorHashOperatorsShouldNotBeUsedQuery() and + queryId = + // `@id` for the `preprocessorHashOperatorsShouldNotBeUsed` query + "c/misra/preprocessor-hash-operators-should-not-be-used" and + ruleId = "RULE-20-10" + or + query = + // `Query` instance for the `forbiddenCharactersInHeaderFileName` query + Preprocessor1Package::forbiddenCharactersInHeaderFileNameQuery() and + queryId = + // `@id` for the `forbiddenCharactersInHeaderFileName` query + "c/misra/forbidden-characters-in-header-file-name" and + ruleId = "RULE-20-2" + or + query = + // `Query` instance for the `identifiersUsedInPreprocessorExpression` query + Preprocessor1Package::identifiersUsedInPreprocessorExpressionQuery() and + queryId = + // `@id` for the `identifiersUsedInPreprocessorExpression` query + "c/misra/identifiers-used-in-preprocessor-expression" and + ruleId = "RULE-20-9" +} + +module Preprocessor1Package { + Query includeDirectivesPrecededByDirectivesOrCommentsQuery() { + //autogenerate `Query` type + result = + // `Query` type for `includeDirectivesPrecededByDirectivesOrComments` query + TQueryC(TPreprocessor1PackageQuery(TIncludeDirectivesPrecededByDirectivesOrCommentsQuery())) + } + + Query preprocessorHashOperatorsShouldNotBeUsedQuery() { + //autogenerate `Query` type + result = + // `Query` type for `preprocessorHashOperatorsShouldNotBeUsed` query + TQueryC(TPreprocessor1PackageQuery(TPreprocessorHashOperatorsShouldNotBeUsedQuery())) + } + + Query forbiddenCharactersInHeaderFileNameQuery() { + //autogenerate `Query` type + result = + // `Query` type for `forbiddenCharactersInHeaderFileName` query + TQueryC(TPreprocessor1PackageQuery(TForbiddenCharactersInHeaderFileNameQuery())) + } + + Query identifiersUsedInPreprocessorExpressionQuery() { + //autogenerate `Query` type + result = + // `Query` type for `identifiersUsedInPreprocessorExpression` query + TQueryC(TPreprocessor1PackageQuery(TIdentifiersUsedInPreprocessorExpressionQuery())) + } +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll new file mode 100644 index 0000000000..1880b8daf0 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/c/RuleMetadata.qll @@ -0,0 +1,17 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import codingstandards.cpp.exclusions.RuleMetadata +//** Import packages for this language **/ +import IO1 +import Preprocessor1 + +/** The TQuery type representing this language * */ +newtype TCQuery = + TIO1PackageQuery(IO1Query q) or + TPreprocessor1PackageQuery(Preprocessor1Query q) + +/** The metadata predicate * */ +predicate isQueryMetadata(Query query, string queryId, string ruleId) { + isIO1QueryMetadata(query, queryId, ruleId) or + isPreprocessor1QueryMetadata(query, queryId, ruleId) +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Allocations.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Allocations.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Allocations.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Allocations.qll index 10cd3dd500..e4550ad95e 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Allocations.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Allocations.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype AllocationsQuery = TPlacementNewNotProperlyAlignedAutosarQuery() or @@ -200,146 +201,146 @@ module AllocationsPackage { //autogenerate `Query` type result = // `Query` type for `placementNewNotProperlyAlignedAutosar` query - TAllocationsPackageQuery(TPlacementNewNotProperlyAlignedAutosarQuery()) + TQueryCPP(TAllocationsPackageQuery(TPlacementNewNotProperlyAlignedAutosarQuery())) } Query placementNewInsufficientStorageAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `placementNewInsufficientStorageAutosar` query - TAllocationsPackageQuery(TPlacementNewInsufficientStorageAutosarQuery()) + TQueryCPP(TAllocationsPackageQuery(TPlacementNewInsufficientStorageAutosarQuery())) } Query doNotUseNonPlacementNewQuery() { //autogenerate `Query` type result = // `Query` type for `doNotUseNonPlacementNew` query - TAllocationsPackageQuery(TDoNotUseNonPlacementNewQuery()) + TQueryCPP(TAllocationsPackageQuery(TDoNotUseNonPlacementNewQuery())) } Query doNotUseNonPlacementDeleteQuery() { //autogenerate `Query` type result = // `Query` type for `doNotUseNonPlacementDelete` query - TAllocationsPackageQuery(TDoNotUseNonPlacementDeleteQuery()) + TQueryCPP(TAllocationsPackageQuery(TDoNotUseNonPlacementDeleteQuery())) } Query dynamicMemoryManagementFailureModeQuery() { //autogenerate `Query` type result = // `Query` type for `dynamicMemoryManagementFailureMode` query - TAllocationsPackageQuery(TDynamicMemoryManagementFailureModeQuery()) + TQueryCPP(TAllocationsPackageQuery(TDynamicMemoryManagementFailureModeQuery())) } Query unnecessaryUseOfDynamicStorageQuery() { //autogenerate `Query` type result = // `Query` type for `unnecessaryUseOfDynamicStorage` query - TAllocationsPackageQuery(TUnnecessaryUseOfDynamicStorageQuery()) + TQueryCPP(TAllocationsPackageQuery(TUnnecessaryUseOfDynamicStorageQuery())) } Query throwingOperatorNewReturnsNullAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `throwingOperatorNewReturnsNullAutosar` query - TAllocationsPackageQuery(TThrowingOperatorNewReturnsNullAutosarQuery()) + TQueryCPP(TAllocationsPackageQuery(TThrowingOperatorNewReturnsNullAutosarQuery())) } Query throwingOperatorNewThrowsInvalidExceptionAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `throwingOperatorNewThrowsInvalidExceptionAutosar` query - TAllocationsPackageQuery(TThrowingOperatorNewThrowsInvalidExceptionAutosarQuery()) + TQueryCPP(TAllocationsPackageQuery(TThrowingOperatorNewThrowsInvalidExceptionAutosarQuery())) } Query throwingNoThrowOperatorNewDeleteAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `throwingNoThrowOperatorNewDeleteAutosar` query - TAllocationsPackageQuery(TThrowingNoThrowOperatorNewDeleteAutosarQuery()) + TQueryCPP(TAllocationsPackageQuery(TThrowingNoThrowOperatorNewDeleteAutosarQuery())) } Query operatorDeleteMissingPartnerAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `operatorDeleteMissingPartnerAutosar` query - TAllocationsPackageQuery(TOperatorDeleteMissingPartnerAutosarQuery()) + TQueryCPP(TAllocationsPackageQuery(TOperatorDeleteMissingPartnerAutosarQuery())) } Query properlyDeallocateDynamicallyAllocatedResourcesQuery() { //autogenerate `Query` type result = // `Query` type for `properlyDeallocateDynamicallyAllocatedResources` query - TAllocationsPackageQuery(TProperlyDeallocateDynamicallyAllocatedResourcesQuery()) + TQueryCPP(TAllocationsPackageQuery(TProperlyDeallocateDynamicallyAllocatedResourcesQuery())) } Query detectAndHandleMemoryAllocationErrorsQuery() { //autogenerate `Query` type result = // `Query` type for `detectAndHandleMemoryAllocationErrors` query - TAllocationsPackageQuery(TDetectAndHandleMemoryAllocationErrorsQuery()) + TQueryCPP(TAllocationsPackageQuery(TDetectAndHandleMemoryAllocationErrorsQuery())) } Query missingConstructorCallForManuallyManagedObjectQuery() { //autogenerate `Query` type result = // `Query` type for `missingConstructorCallForManuallyManagedObject` query - TAllocationsPackageQuery(TMissingConstructorCallForManuallyManagedObjectQuery()) + TQueryCPP(TAllocationsPackageQuery(TMissingConstructorCallForManuallyManagedObjectQuery())) } Query missingDestructorCallForManuallyManagedObjectQuery() { //autogenerate `Query` type result = // `Query` type for `missingDestructorCallForManuallyManagedObject` query - TAllocationsPackageQuery(TMissingDestructorCallForManuallyManagedObjectQuery()) + TQueryCPP(TAllocationsPackageQuery(TMissingDestructorCallForManuallyManagedObjectQuery())) } Query placementNewNotProperlyAlignedCertQuery() { //autogenerate `Query` type result = // `Query` type for `placementNewNotProperlyAlignedCert` query - TAllocationsPackageQuery(TPlacementNewNotProperlyAlignedCertQuery()) + TQueryCPP(TAllocationsPackageQuery(TPlacementNewNotProperlyAlignedCertQuery())) } Query placementNewInsufficientStorageCertQuery() { //autogenerate `Query` type result = // `Query` type for `placementNewInsufficientStorageCert` query - TAllocationsPackageQuery(TPlacementNewInsufficientStorageCertQuery()) + TQueryCPP(TAllocationsPackageQuery(TPlacementNewInsufficientStorageCertQuery())) } Query throwingOperatorNewReturnsNullCertQuery() { //autogenerate `Query` type result = // `Query` type for `throwingOperatorNewReturnsNullCert` query - TAllocationsPackageQuery(TThrowingOperatorNewReturnsNullCertQuery()) + TQueryCPP(TAllocationsPackageQuery(TThrowingOperatorNewReturnsNullCertQuery())) } Query throwingOperatorNewThrowsInvalidExceptionCertQuery() { //autogenerate `Query` type result = // `Query` type for `throwingOperatorNewThrowsInvalidExceptionCert` query - TAllocationsPackageQuery(TThrowingOperatorNewThrowsInvalidExceptionCertQuery()) + TQueryCPP(TAllocationsPackageQuery(TThrowingOperatorNewThrowsInvalidExceptionCertQuery())) } Query throwingNoThrowOperatorNewDeleteCertQuery() { //autogenerate `Query` type result = // `Query` type for `throwingNoThrowOperatorNewDeleteCert` query - TAllocationsPackageQuery(TThrowingNoThrowOperatorNewDeleteCertQuery()) + TQueryCPP(TAllocationsPackageQuery(TThrowingNoThrowOperatorNewDeleteCertQuery())) } Query operatorDeleteMissingPartnerCertQuery() { //autogenerate `Query` type result = // `Query` type for `operatorDeleteMissingPartnerCert` query - TAllocationsPackageQuery(TOperatorDeleteMissingPartnerCertQuery()) + TQueryCPP(TAllocationsPackageQuery(TOperatorDeleteMissingPartnerCertQuery())) } Query usingDefaultOperatorNewForOverAlignedTypesQuery() { //autogenerate `Query` type result = // `Query` type for `usingDefaultOperatorNewForOverAlignedTypes` query - TAllocationsPackageQuery(TUsingDefaultOperatorNewForOverAlignedTypesQuery()) + TQueryCPP(TAllocationsPackageQuery(TUsingDefaultOperatorNewForOverAlignedTypesQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/BannedFunctions.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedFunctions.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/BannedFunctions.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedFunctions.qll index 6a89a9a3b6..bd611a42ec 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/BannedFunctions.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedFunctions.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype BannedFunctionsQuery = TFunctionsMallocCallocReallocAndFreeUsedQuery() or @@ -110,76 +111,76 @@ module BannedFunctionsPackage { //autogenerate `Query` type result = // `Query` type for `functionsMallocCallocReallocAndFreeUsed` query - TBannedFunctionsPackageQuery(TFunctionsMallocCallocReallocAndFreeUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TFunctionsMallocCallocReallocAndFreeUsedQuery())) } Query bindUsedQuery() { //autogenerate `Query` type result = // `Query` type for `bindUsed` query - TBannedFunctionsPackageQuery(TBindUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TBindUsedQuery())) } Query pseudorandomNumbersGeneratedUsingRandQuery() { //autogenerate `Query` type result = // `Query` type for `pseudorandomNumbersGeneratedUsingRand` query - TBannedFunctionsPackageQuery(TPseudorandomNumbersGeneratedUsingRandQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TPseudorandomNumbersGeneratedUsingRandQuery())) } Query setjmpMacroAndTheLongjmpFunctionUsedQuery() { //autogenerate `Query` type result = // `Query` type for `setjmpMacroAndTheLongjmpFunctionUsed` query - TBannedFunctionsPackageQuery(TSetjmpMacroAndTheLongjmpFunctionUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TSetjmpMacroAndTheLongjmpFunctionUsedQuery())) } Query libraryFunctionsAbortExitGetenvAndSystemFromLibraryCstdlibUsedQuery() { //autogenerate `Query` type result = // `Query` type for `libraryFunctionsAbortExitGetenvAndSystemFromLibraryCstdlibUsed` query - TBannedFunctionsPackageQuery(TLibraryFunctionsAbortExitGetenvAndSystemFromLibraryCstdlibUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TLibraryFunctionsAbortExitGetenvAndSystemFromLibraryCstdlibUsedQuery())) } Query timeHandlingFunctionsOfLibraryCtimeUsedQuery() { //autogenerate `Query` type result = // `Query` type for `timeHandlingFunctionsOfLibraryCtimeUsed` query - TBannedFunctionsPackageQuery(TTimeHandlingFunctionsOfLibraryCtimeUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TTimeHandlingFunctionsOfLibraryCtimeUsedQuery())) } Query unboundedFunctionsOfLibraryCstringUsedQuery() { //autogenerate `Query` type result = // `Query` type for `unboundedFunctionsOfLibraryCstringUsed` query - TBannedFunctionsPackageQuery(TUnboundedFunctionsOfLibraryCstringUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TUnboundedFunctionsOfLibraryCstringUsedQuery())) } Query macroOffsetofUsedQuery() { //autogenerate `Query` type result = // `Query` type for `macroOffsetofUsed` query - TBannedFunctionsPackageQuery(TMacroOffsetofUsedQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TMacroOffsetofUsedQuery())) } Query doNotUseSetjmpOrLongjmpQuery() { //autogenerate `Query` type result = // `Query` type for `doNotUseSetjmpOrLongjmp` query - TBannedFunctionsPackageQuery(TDoNotUseSetjmpOrLongjmpQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TDoNotUseSetjmpOrLongjmpQuery())) } Query doNotUseRandForGeneratingPseudorandomNumbersQuery() { //autogenerate `Query` type result = // `Query` type for `doNotUseRandForGeneratingPseudorandomNumbers` query - TBannedFunctionsPackageQuery(TDoNotUseRandForGeneratingPseudorandomNumbersQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TDoNotUseRandForGeneratingPseudorandomNumbersQuery())) } Query preferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctionsQuery() { //autogenerate `Query` type result = // `Query` type for `preferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctions` query - TBannedFunctionsPackageQuery(TPreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctionsQuery()) + TQueryCPP(TBannedFunctionsPackageQuery(TPreferSpecialMemberFunctionsAndOverloadedOperatorsToCStandardLibraryFunctionsQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/BannedLibraries.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedLibraries.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/BannedLibraries.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedLibraries.qll index c3710223df..0672896465 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/BannedLibraries.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedLibraries.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype BannedLibrariesQuery = TReservedIdentifiersMacrosAndFunctionsAreDefinedRedefinedOrUndefinedQuery() or @@ -119,83 +120,83 @@ module BannedLibrariesPackage { //autogenerate `Query` type result = // `Query` type for `reservedIdentifiersMacrosAndFunctionsAreDefinedRedefinedOrUndefined` query - TBannedLibrariesPackageQuery(TReservedIdentifiersMacrosAndFunctionsAreDefinedRedefinedOrUndefinedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TReservedIdentifiersMacrosAndFunctionsAreDefinedRedefinedOrUndefinedQuery())) } Query cLibraryFacilitiesNotAccessedThroughCPPLibraryHeadersQuery() { //autogenerate `Query` type result = // `Query` type for `cLibraryFacilitiesNotAccessedThroughCPPLibraryHeaders` query - TBannedLibrariesPackageQuery(TCLibraryFacilitiesNotAccessedThroughCPPLibraryHeadersQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TCLibraryFacilitiesNotAccessedThroughCPPLibraryHeadersQuery())) } Query localeFunctionsUsedQuery() { //autogenerate `Query` type result = // `Query` type for `localeFunctionsUsed` query - TBannedLibrariesPackageQuery(TLocaleFunctionsUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TLocaleFunctionsUsedQuery())) } Query localeMacrosUsedQuery() { //autogenerate `Query` type result = // `Query` type for `localeMacrosUsed` query - TBannedLibrariesPackageQuery(TLocaleMacrosUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TLocaleMacrosUsedQuery())) } Query localeTypeLConvUsedQuery() { //autogenerate `Query` type result = // `Query` type for `localeTypeLConvUsed` query - TBannedLibrariesPackageQuery(TLocaleTypeLConvUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TLocaleTypeLConvUsedQuery())) } Query csignalFunctionsUsedQuery() { //autogenerate `Query` type result = // `Query` type for `csignalFunctionsUsed` query - TBannedLibrariesPackageQuery(TCsignalFunctionsUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TCsignalFunctionsUsedQuery())) } Query csignalTypesUsedQuery() { //autogenerate `Query` type result = // `Query` type for `csignalTypesUsed` query - TBannedLibrariesPackageQuery(TCsignalTypesUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TCsignalTypesUsedQuery())) } Query errnoUsedQuery() { //autogenerate `Query` type result = // `Query` type for `errnoUsed` query - TBannedLibrariesPackageQuery(TErrnoUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TErrnoUsedQuery())) } Query cstdioFunctionsUsedQuery() { //autogenerate `Query` type result = // `Query` type for `cstdioFunctionsUsed` query - TBannedLibrariesPackageQuery(TCstdioFunctionsUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TCstdioFunctionsUsedQuery())) } Query cstdioMacrosUsedQuery() { //autogenerate `Query` type result = // `Query` type for `cstdioMacrosUsed` query - TBannedLibrariesPackageQuery(TCstdioMacrosUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TCstdioMacrosUsedQuery())) } Query cstdioTypesUsedQuery() { //autogenerate `Query` type result = // `Query` type for `cstdioTypesUsed` query - TBannedLibrariesPackageQuery(TCstdioTypesUsedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TCstdioTypesUsedQuery())) } Query usageOfAssemblerNotDocumentedQuery() { //autogenerate `Query` type result = // `Query` type for `usageOfAssemblerNotDocumented` query - TBannedLibrariesPackageQuery(TUsageOfAssemblerNotDocumentedQuery()) + TQueryCPP(TBannedLibrariesPackageQuery(TUsageOfAssemblerNotDocumentedQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/BannedSyntax.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedSyntax.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/BannedSyntax.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedSyntax.qll index cf5a5d2e60..bd9b0d4924 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/BannedSyntax.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedSyntax.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype BannedSyntaxQuery = TFriendDeclarationsUsedQuery() or @@ -164,118 +165,118 @@ module BannedSyntaxPackage { //autogenerate `Query` type result = // `Query` type for `friendDeclarationsUsed` query - TBannedSyntaxPackageQuery(TFriendDeclarationsUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TFriendDeclarationsUsedQuery())) } Query cStyleArraysUsedQuery() { //autogenerate `Query` type result = // `Query` type for `cStyleArraysUsed` query - TBannedSyntaxPackageQuery(TCStyleArraysUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TCStyleArraysUsedQuery())) } Query volatileKeywordUsedQuery() { //autogenerate `Query` type result = // `Query` type for `volatileKeywordUsed` query - TBannedSyntaxPackageQuery(TVolatileKeywordUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TVolatileKeywordUsedQuery())) } Query ternaryConditionalOperatorUsedAsSubExpressionQuery() { //autogenerate `Query` type result = // `Query` type for `ternaryConditionalOperatorUsedAsSubExpression` query - TBannedSyntaxPackageQuery(TTernaryConditionalOperatorUsedAsSubExpressionQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TTernaryConditionalOperatorUsedAsSubExpressionQuery())) } Query dynamicCastShouldNotBeUsedQuery() { //autogenerate `Query` type result = // `Query` type for `dynamicCastShouldNotBeUsed` query - TBannedSyntaxPackageQuery(TDynamicCastShouldNotBeUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TDynamicCastShouldNotBeUsedQuery())) } Query traditionalCStyleCastsUsedQuery() { //autogenerate `Query` type result = // `Query` type for `traditionalCStyleCastsUsed` query - TBannedSyntaxPackageQuery(TTraditionalCStyleCastsUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TTraditionalCStyleCastsUsedQuery())) } Query reinterpretCastUsedQuery() { //autogenerate `Query` type result = // `Query` type for `reinterpretCastUsed` query - TBannedSyntaxPackageQuery(TReinterpretCastUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TReinterpretCastUsedQuery())) } Query gotoStatementUsedQuery() { //autogenerate `Query` type result = // `Query` type for `gotoStatementUsed` query - TBannedSyntaxPackageQuery(TGotoStatementUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TGotoStatementUsedQuery())) } Query registerKeywordUsedQuery() { //autogenerate `Query` type result = // `Query` type for `registerKeywordUsed` query - TBannedSyntaxPackageQuery(TRegisterKeywordUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TRegisterKeywordUsedQuery())) } Query typedefSpecifierUsedQuery() { //autogenerate `Query` type result = // `Query` type for `typedefSpecifierUsed` query - TBannedSyntaxPackageQuery(TTypedefSpecifierUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TTypedefSpecifierUsedQuery())) } Query asmDeclarationUsedQuery() { //autogenerate `Query` type result = // `Query` type for `asmDeclarationUsed` query - TBannedSyntaxPackageQuery(TAsmDeclarationUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TAsmDeclarationUsedQuery())) } Query functionsDefinedUsingTheEllipsisNotationQuery() { //autogenerate `Query` type result = // `Query` type for `functionsDefinedUsingTheEllipsisNotation` query - TBannedSyntaxPackageQuery(TFunctionsDefinedUsingTheEllipsisNotationQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TFunctionsDefinedUsingTheEllipsisNotationQuery())) } Query unionsUsedQuery() { //autogenerate `Query` type result = // `Query` type for `unionsUsed` query - TBannedSyntaxPackageQuery(TUnionsUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TUnionsUsedQuery())) } Query commaOperatorUsedQuery() { //autogenerate `Query` type result = // `Query` type for `commaOperatorUsed` query - TBannedSyntaxPackageQuery(TCommaOperatorUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TCommaOperatorUsedQuery())) } Query usingDirectivesUsedQuery() { //autogenerate `Query` type result = // `Query` type for `usingDirectivesUsed` query - TBannedSyntaxPackageQuery(TUsingDirectivesUsedQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TUsingDirectivesUsedQuery())) } Query usingDeclarationsUsedInHeaderFilesQuery() { //autogenerate `Query` type result = // `Query` type for `usingDeclarationsUsedInHeaderFiles` query - TBannedSyntaxPackageQuery(TUsingDeclarationsUsedInHeaderFilesQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TUsingDeclarationsUsedInHeaderFilesQuery())) } Query doNotDefineACStyleVariadicFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `doNotDefineACStyleVariadicFunction` query - TBannedSyntaxPackageQuery(TDoNotDefineACStyleVariadicFunctionQuery()) + TQueryCPP(TBannedSyntaxPackageQuery(TDoNotDefineACStyleVariadicFunctionQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/BannedTypes.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedTypes.qll similarity index 82% rename from cpp/common/src/codingstandards/cpp/exclusions/BannedTypes.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedTypes.qll index 06ac0ecf2d..a03f046633 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/BannedTypes.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/BannedTypes.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype BannedTypesQuery = TTypeLongDoubleUsedQuery() or @@ -47,27 +48,27 @@ module BannedTypesPackage { //autogenerate `Query` type result = // `Query` type for `typeLongDoubleUsed` query - TBannedTypesPackageQuery(TTypeLongDoubleUsedQuery()) + TQueryCPP(TBannedTypesPackageQuery(TTypeLongDoubleUsedQuery())) } Query vectorboolSpecializationUsedQuery() { //autogenerate `Query` type result = // `Query` type for `vectorboolSpecializationUsed` query - TBannedTypesPackageQuery(TVectorboolSpecializationUsedQuery()) + TQueryCPP(TBannedTypesPackageQuery(TVectorboolSpecializationUsedQuery())) } Query autoPtrTypeUsedQuery() { //autogenerate `Query` type result = // `Query` type for `autoPtrTypeUsed` query - TBannedTypesPackageQuery(TAutoPtrTypeUsedQuery()) + TQueryCPP(TBannedTypesPackageQuery(TAutoPtrTypeUsedQuery())) } Query typeWcharTUsedQuery() { //autogenerate `Query` type result = // `Query` type for `typeWcharTUsed` query - TBannedTypesPackageQuery(TTypeWcharTUsedQuery()) + TQueryCPP(TBannedTypesPackageQuery(TTypeWcharTUsedQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Classes.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll similarity index 86% rename from cpp/common/src/codingstandards/cpp/exclusions/Classes.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll index fa3a354e70..a185b76287 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Classes.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ClassesQuery = TNonPodTypeShouldBeDefinedAsClassQuery() or @@ -173,125 +174,125 @@ module ClassesPackage { //autogenerate `Query` type result = // `Query` type for `nonPodTypeShouldBeDefinedAsClass` query - TClassesPackageQuery(TNonPodTypeShouldBeDefinedAsClassQuery()) + TQueryCPP(TClassesPackageQuery(TNonPodTypeShouldBeDefinedAsClassQuery())) } Query typeDefinedAsStructHasOnlyPublicDataMembersQuery() { //autogenerate `Query` type result = // `Query` type for `typeDefinedAsStructHasOnlyPublicDataMembers` query - TClassesPackageQuery(TTypeDefinedAsStructHasOnlyPublicDataMembersQuery()) + TQueryCPP(TClassesPackageQuery(TTypeDefinedAsStructHasOnlyPublicDataMembersQuery())) } Query typeDefinedAsStructHasNoMethodsQuery() { //autogenerate `Query` type result = // `Query` type for `typeDefinedAsStructHasNoMethods` query - TClassesPackageQuery(TTypeDefinedAsStructHasNoMethodsQuery()) + TQueryCPP(TClassesPackageQuery(TTypeDefinedAsStructHasNoMethodsQuery())) } Query typeDefinedAsStructIsNotBaseOfOtherClassOrStructQuery() { //autogenerate `Query` type result = // `Query` type for `typeDefinedAsStructIsNotBaseOfOtherClassOrStruct` query - TClassesPackageQuery(TTypeDefinedAsStructIsNotBaseOfOtherClassOrStructQuery()) + TQueryCPP(TClassesPackageQuery(TTypeDefinedAsStructIsNotBaseOfOtherClassOrStructQuery())) } Query typeDefinedAsStructIsDoesNotInheritFromStructOrClassQuery() { //autogenerate `Query` type result = // `Query` type for `typeDefinedAsStructIsDoesNotInheritFromStructOrClass` query - TClassesPackageQuery(TTypeDefinedAsStructIsDoesNotInheritFromStructOrClassQuery()) + TQueryCPP(TClassesPackageQuery(TTypeDefinedAsStructIsDoesNotInheritFromStructOrClassQuery())) } Query missingSpecialMemberFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `missingSpecialMemberFunction` query - TClassesPackageQuery(TMissingSpecialMemberFunctionQuery()) + TQueryCPP(TClassesPackageQuery(TMissingSpecialMemberFunctionQuery())) } Query classDataMembersInitializationConditionQuery() { //autogenerate `Query` type result = // `Query` type for `classDataMembersInitializationCondition` query - TClassesPackageQuery(TClassDataMembersInitializationConditionQuery()) + TQueryCPP(TClassesPackageQuery(TClassDataMembersInitializationConditionQuery())) } Query redundantMemberFunctionsShouldBeDefaultedOrLeftUndefinedQuery() { //autogenerate `Query` type result = // `Query` type for `redundantMemberFunctionsShouldBeDefaultedOrLeftUndefined` query - TClassesPackageQuery(TRedundantMemberFunctionsShouldBeDefaultedOrLeftUndefinedQuery()) + TQueryCPP(TClassesPackageQuery(TRedundantMemberFunctionsShouldBeDefaultedOrLeftUndefinedQuery())) } Query nonTemplateMemberDefinedInTemplateQuery() { //autogenerate `Query` type result = // `Query` type for `nonTemplateMemberDefinedInTemplate` query - TClassesPackageQuery(TNonTemplateMemberDefinedInTemplateQuery()) + TQueryCPP(TClassesPackageQuery(TNonTemplateMemberDefinedInTemplateQuery())) } Query trivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `trivialOrTemplateFunctionDefinedOutsideClassDefinition` query - TClassesPackageQuery(TTrivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery()) + TQueryCPP(TClassesPackageQuery(TTrivialOrTemplateFunctionDefinedOutsideClassDefinitionQuery())) } Query nonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `nonTrivialNonTemplateFunctionDefinedInsideClassDefinition` query - TClassesPackageQuery(TNonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery()) + TQueryCPP(TClassesPackageQuery(TNonTrivialNonTemplateFunctionDefinedInsideClassDefinitionQuery())) } Query inParametersForNotCheapToCopyTypesNotPassedByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `inParametersForNotCheapToCopyTypesNotPassedByReference` query - TClassesPackageQuery(TInParametersForNotCheapToCopyTypesNotPassedByReferenceQuery()) + TQueryCPP(TClassesPackageQuery(TInParametersForNotCheapToCopyTypesNotPassedByReferenceQuery())) } Query inParametersForCheapToCopyTypesNotPassedByValueQuery() { //autogenerate `Query` type result = // `Query` type for `inParametersForCheapToCopyTypesNotPassedByValue` query - TClassesPackageQuery(TInParametersForCheapToCopyTypesNotPassedByValueQuery()) + TQueryCPP(TClassesPackageQuery(TInParametersForCheapToCopyTypesNotPassedByValueQuery())) } Query returnsNonConstRawPointersOrReferencesToPrivateOrProtectedDataQuery() { //autogenerate `Query` type result = // `Query` type for `returnsNonConstRawPointersOrReferencesToPrivateOrProtectedData` query - TClassesPackageQuery(TReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedDataQuery()) + TQueryCPP(TClassesPackageQuery(TReturnsNonConstRawPointersOrReferencesToPrivateOrProtectedDataQuery())) } Query dataTypesUsedForInterfacingWithHardwareOrProtocolsMustBeTrivialAndStandardLayoutQuery() { //autogenerate `Query` type result = // `Query` type for `dataTypesUsedForInterfacingWithHardwareOrProtocolsMustBeTrivialAndStandardLayout` query - TClassesPackageQuery(TDataTypesUsedForInterfacingWithHardwareOrProtocolsMustBeTrivialAndStandardLayoutQuery()) + TQueryCPP(TClassesPackageQuery(TDataTypesUsedForInterfacingWithHardwareOrProtocolsMustBeTrivialAndStandardLayoutQuery())) } Query dataTypesUsedForInterfacingWithHardwareOrProtocolsMustContainOnlyDefinedDataTypeSizesQuery() { //autogenerate `Query` type result = // `Query` type for `dataTypesUsedForInterfacingWithHardwareOrProtocolsMustContainOnlyDefinedDataTypeSizes` query - TClassesPackageQuery(TDataTypesUsedForInterfacingWithHardwareOrProtocolsMustContainOnlyDefinedDataTypeSizesQuery()) + TQueryCPP(TClassesPackageQuery(TDataTypesUsedForInterfacingWithHardwareOrProtocolsMustContainOnlyDefinedDataTypeSizesQuery())) } Query memberDataInNonPodClassTypesNotPrivateQuery() { //autogenerate `Query` type result = // `Query` type for `memberDataInNonPodClassTypesNotPrivate` query - TClassesPackageQuery(TMemberDataInNonPodClassTypesNotPrivateQuery()) + TQueryCPP(TClassesPackageQuery(TMemberDataInNonPodClassTypesNotPrivateQuery())) } Query offsetUsedOnInvalidTypeOrMemberQuery() { //autogenerate `Query` type result = // `Query` type for `offsetUsedOnInvalidTypeOrMember` query - TClassesPackageQuery(TOffsetUsedOnInvalidTypeOrMemberQuery()) + TQueryCPP(TClassesPackageQuery(TOffsetUsedOnInvalidTypeOrMemberQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Comments.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Comments.qll similarity index 83% rename from cpp/common/src/codingstandards/cpp/exclusions/Comments.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Comments.qll index 2b9bfcabcf..0c06102ec7 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Comments.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Comments.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype CommentsQuery = TSingleLineCommentEndsWithSlashQuery() or @@ -56,34 +57,34 @@ module CommentsPackage { //autogenerate `Query` type result = // `Query` type for `singleLineCommentEndsWithSlash` query - TCommentsPackageQuery(TSingleLineCommentEndsWithSlashQuery()) + TQueryCPP(TCommentsPackageQuery(TSingleLineCommentEndsWithSlashQuery())) } Query sectionsOfCodeCommentedOutQuery() { //autogenerate `Query` type result = // `Query` type for `sectionsOfCodeCommentedOut` query - TCommentsPackageQuery(TSectionsOfCodeCommentedOutQuery()) + TQueryCPP(TCommentsPackageQuery(TSectionsOfCodeCommentedOutQuery())) } Query undocumentedUserDefinedTypeQuery() { //autogenerate `Query` type result = // `Query` type for `undocumentedUserDefinedType` query - TCommentsPackageQuery(TUndocumentedUserDefinedTypeQuery()) + TQueryCPP(TCommentsPackageQuery(TUndocumentedUserDefinedTypeQuery())) } Query slashStarUsedWithinACStyleCommentQuery() { //autogenerate `Query` type result = // `Query` type for `slashStarUsedWithinACStyleComment` query - TCommentsPackageQuery(TSlashStarUsedWithinACStyleCommentQuery()) + TQueryCPP(TCommentsPackageQuery(TSlashStarUsedWithinACStyleCommentQuery())) } Query nullOnSharedLineQuery() { //autogenerate `Query` type result = // `Query` type for `nullOnSharedLine` query - TCommentsPackageQuery(TNullOnSharedLineQuery()) + TQueryCPP(TCommentsPackageQuery(TNullOnSharedLineQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Concurrency.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Concurrency.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Concurrency.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Concurrency.qll index 957c58e36c..4c67e654a4 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Concurrency.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ConcurrencyQuery = TDoNotAllowAMutexToGoOutOfScopeWhileLockedQuery() or @@ -92,62 +93,62 @@ module ConcurrencyPackage { //autogenerate `Query` type result = // `Query` type for `doNotAllowAMutexToGoOutOfScopeWhileLocked` query - TConcurrencyPackageQuery(TDoNotAllowAMutexToGoOutOfScopeWhileLockedQuery()) + TQueryCPP(TConcurrencyPackageQuery(TDoNotAllowAMutexToGoOutOfScopeWhileLockedQuery())) } Query doNotDestroyAMutexWhileItIsLockedQuery() { //autogenerate `Query` type result = // `Query` type for `doNotDestroyAMutexWhileItIsLocked` query - TConcurrencyPackageQuery(TDoNotDestroyAMutexWhileItIsLockedQuery()) + TQueryCPP(TConcurrencyPackageQuery(TDoNotDestroyAMutexWhileItIsLockedQuery())) } Query ensureActivelyHeldLocksAreReleasedOnExceptionalConditionsQuery() { //autogenerate `Query` type result = // `Query` type for `ensureActivelyHeldLocksAreReleasedOnExceptionalConditions` query - TConcurrencyPackageQuery(TEnsureActivelyHeldLocksAreReleasedOnExceptionalConditionsQuery()) + TQueryCPP(TConcurrencyPackageQuery(TEnsureActivelyHeldLocksAreReleasedOnExceptionalConditionsQuery())) } Query preventDataRacesWhenAccessingBitFieldsFromMultipleThreadsQuery() { //autogenerate `Query` type result = // `Query` type for `preventDataRacesWhenAccessingBitFieldsFromMultipleThreads` query - TConcurrencyPackageQuery(TPreventDataRacesWhenAccessingBitFieldsFromMultipleThreadsQuery()) + TQueryCPP(TConcurrencyPackageQuery(TPreventDataRacesWhenAccessingBitFieldsFromMultipleThreadsQuery())) } Query deadlockByLockingInPredefinedOrderQuery() { //autogenerate `Query` type result = // `Query` type for `deadlockByLockingInPredefinedOrder` query - TConcurrencyPackageQuery(TDeadlockByLockingInPredefinedOrderQuery()) + TQueryCPP(TConcurrencyPackageQuery(TDeadlockByLockingInPredefinedOrderQuery())) } Query wrapFunctionsThatCanSpuriouslyWakeUpInLoopQuery() { //autogenerate `Query` type result = // `Query` type for `wrapFunctionsThatCanSpuriouslyWakeUpInLoop` query - TConcurrencyPackageQuery(TWrapFunctionsThatCanSpuriouslyWakeUpInLoopQuery()) + TQueryCPP(TConcurrencyPackageQuery(TWrapFunctionsThatCanSpuriouslyWakeUpInLoopQuery())) } Query preserveThreadSafetyAndLivenessWhenUsingConditionVariablesQuery() { //autogenerate `Query` type result = // `Query` type for `preserveThreadSafetyAndLivenessWhenUsingConditionVariables` query - TConcurrencyPackageQuery(TPreserveThreadSafetyAndLivenessWhenUsingConditionVariablesQuery()) + TQueryCPP(TConcurrencyPackageQuery(TPreserveThreadSafetyAndLivenessWhenUsingConditionVariablesQuery())) } Query doNotSpeculativelyLockALockedNonRecursiveMutexQuery() { //autogenerate `Query` type result = // `Query` type for `doNotSpeculativelyLockALockedNonRecursiveMutex` query - TConcurrencyPackageQuery(TDoNotSpeculativelyLockALockedNonRecursiveMutexQuery()) + TQueryCPP(TConcurrencyPackageQuery(TDoNotSpeculativelyLockALockedNonRecursiveMutexQuery())) } Query lockedALockedNonRecursiveMutexAuditQuery() { //autogenerate `Query` type result = // `Query` type for `lockedALockedNonRecursiveMutexAudit` query - TConcurrencyPackageQuery(TLockedALockedNonRecursiveMutexAuditQuery()) + TQueryCPP(TConcurrencyPackageQuery(TLockedALockedNonRecursiveMutexAuditQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Conditionals.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Conditionals.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Conditionals.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Conditionals.qll index 99322a04b6..4ca7053d08 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Conditionals.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Conditionals.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ConditionalsQuery = TNonBooleanIfConditionQuery() or @@ -164,118 +165,118 @@ module ConditionalsPackage { //autogenerate `Query` type result = // `Query` type for `nonBooleanIfCondition` query - TConditionalsPackageQuery(TNonBooleanIfConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TNonBooleanIfConditionQuery())) } Query nonBooleanIterationConditionQuery() { //autogenerate `Query` type result = // `Query` type for `nonBooleanIterationCondition` query - TConditionalsPackageQuery(TNonBooleanIterationConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TNonBooleanIterationConditionQuery())) } Query switchLessThanTwoCasesQuery() { //autogenerate `Query` type result = // `Query` type for `switchLessThanTwoCases` query - TConditionalsPackageQuery(TSwitchLessThanTwoCasesQuery()) + TQueryCPP(TConditionalsPackageQuery(TSwitchLessThanTwoCasesQuery())) } Query switchCompoundConditionQuery() { //autogenerate `Query` type result = // `Query` type for `switchCompoundCondition` query - TConditionalsPackageQuery(TSwitchCompoundConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TSwitchCompoundConditionQuery())) } Query loopCompoundConditionQuery() { //autogenerate `Query` type result = // `Query` type for `loopCompoundCondition` query - TConditionalsPackageQuery(TLoopCompoundConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TLoopCompoundConditionQuery())) } Query ifCompoundConditionQuery() { //autogenerate `Query` type result = // `Query` type for `ifCompoundCondition` query - TConditionalsPackageQuery(TIfCompoundConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TIfCompoundConditionQuery())) } Query ifElseTerminationConditionQuery() { //autogenerate `Query` type result = // `Query` type for `ifElseTerminationCondition` query - TConditionalsPackageQuery(TIfElseTerminationConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TIfElseTerminationConditionQuery())) } Query switchDoesNotStartWithCaseQuery() { //autogenerate `Query` type result = // `Query` type for `switchDoesNotStartWithCase` query - TConditionalsPackageQuery(TSwitchDoesNotStartWithCaseQuery()) + TQueryCPP(TConditionalsPackageQuery(TSwitchDoesNotStartWithCaseQuery())) } Query switchStatementNotWellFormedQuery() { //autogenerate `Query` type result = // `Query` type for `switchStatementNotWellFormed` query - TConditionalsPackageQuery(TSwitchStatementNotWellFormedQuery()) + TQueryCPP(TConditionalsPackageQuery(TSwitchStatementNotWellFormedQuery())) } Query nestedCaseInSwitchQuery() { //autogenerate `Query` type result = // `Query` type for `nestedCaseInSwitch` query - TConditionalsPackageQuery(TNestedCaseInSwitchQuery()) + TQueryCPP(TConditionalsPackageQuery(TNestedCaseInSwitchQuery())) } Query nonEmptySwitchClauseDoesNotTerminateQuery() { //autogenerate `Query` type result = // `Query` type for `nonEmptySwitchClauseDoesNotTerminate` query - TConditionalsPackageQuery(TNonEmptySwitchClauseDoesNotTerminateQuery()) + TQueryCPP(TConditionalsPackageQuery(TNonEmptySwitchClauseDoesNotTerminateQuery())) } Query missingDefaultInSwitchQuery() { //autogenerate `Query` type result = // `Query` type for `missingDefaultInSwitch` query - TConditionalsPackageQuery(TMissingDefaultInSwitchQuery()) + TQueryCPP(TConditionalsPackageQuery(TMissingDefaultInSwitchQuery())) } Query switchFinalClauseNotDefaultQuery() { //autogenerate `Query` type result = // `Query` type for `switchFinalClauseNotDefault` query - TConditionalsPackageQuery(TSwitchFinalClauseNotDefaultQuery()) + TQueryCPP(TConditionalsPackageQuery(TSwitchFinalClauseNotDefaultQuery())) } Query booleanInSwitchConditionQuery() { //autogenerate `Query` type result = // `Query` type for `booleanInSwitchCondition` query - TConditionalsPackageQuery(TBooleanInSwitchConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TBooleanInSwitchConditionQuery())) } Query gotoBlockConditionQuery() { //autogenerate `Query` type result = // `Query` type for `gotoBlockCondition` query - TConditionalsPackageQuery(TGotoBlockConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TGotoBlockConditionQuery())) } Query gotoStatementJumpConditionQuery() { //autogenerate `Query` type result = // `Query` type for `gotoStatementJumpCondition` query - TConditionalsPackageQuery(TGotoStatementJumpConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TGotoStatementJumpConditionQuery())) } Query continueInForLoopConditionQuery() { //autogenerate `Query` type result = // `Query` type for `continueInForLoopCondition` query - TConditionalsPackageQuery(TContinueInForLoopConditionQuery()) + TQueryCPP(TConditionalsPackageQuery(TContinueInForLoopConditionQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Const.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Const.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll index 42319a62d1..0b2c492115 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Const.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Const.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ConstQuery = TRemoveConstOrVolatileQualificationAutosarQuery() or @@ -128,90 +129,90 @@ module ConstPackage { //autogenerate `Query` type result = // `Query` type for `removeConstOrVolatileQualificationAutosar` query - TConstPackageQuery(TRemoveConstOrVolatileQualificationAutosarQuery()) + TQueryCPP(TConstPackageQuery(TRemoveConstOrVolatileQualificationAutosarQuery())) } Query declarationUnmodifiedParamMissingConstSpecifierQuery() { //autogenerate `Query` type result = // `Query` type for `declarationUnmodifiedParamMissingConstSpecifier` query - TConstPackageQuery(TDeclarationUnmodifiedParamMissingConstSpecifierQuery()) + TQueryCPP(TConstPackageQuery(TDeclarationUnmodifiedParamMissingConstSpecifierQuery())) } Query declarationUnmodifiedObjectMissingConstSpecifierQuery() { //autogenerate `Query` type result = // `Query` type for `declarationUnmodifiedObjectMissingConstSpecifier` query - TConstPackageQuery(TDeclarationUnmodifiedObjectMissingConstSpecifierQuery()) + TQueryCPP(TConstPackageQuery(TDeclarationUnmodifiedObjectMissingConstSpecifierQuery())) } Query variableMissingConstexprQuery() { //autogenerate `Query` type result = // `Query` type for `variableMissingConstexpr` query - TConstPackageQuery(TVariableMissingConstexprQuery()) + TQueryCPP(TConstPackageQuery(TVariableMissingConstexprQuery())) } Query functionMissingConstexprQuery() { //autogenerate `Query` type result = // `Query` type for `functionMissingConstexpr` query - TConstPackageQuery(TFunctionMissingConstexprQuery()) + TQueryCPP(TConstPackageQuery(TFunctionMissingConstexprQuery())) } Query cvQualifiersNotPlacedOnTheRightHandSideQuery() { //autogenerate `Query` type result = // `Query` type for `cvQualifiersNotPlacedOnTheRightHandSide` query - TConstPackageQuery(TCvQualifiersNotPlacedOnTheRightHandSideQuery()) + TQueryCPP(TConstPackageQuery(TCvQualifiersNotPlacedOnTheRightHandSideQuery())) } Query outputParametersUsedQuery() { //autogenerate `Query` type result = // `Query` type for `outputParametersUsed` query - TConstPackageQuery(TOutputParametersUsedQuery()) + TQueryCPP(TConstPackageQuery(TOutputParametersUsedQuery())) } Query inOutParametersDeclaredAsTNotModifiedQuery() { //autogenerate `Query` type result = // `Query` type for `inOutParametersDeclaredAsTNotModified` query - TConstPackageQuery(TInOutParametersDeclaredAsTNotModifiedQuery()) + TQueryCPP(TConstPackageQuery(TInOutParametersDeclaredAsTNotModifiedQuery())) } Query pointerOrReferenceParameterToConstQuery() { //autogenerate `Query` type result = // `Query` type for `pointerOrReferenceParameterToConst` query - TConstPackageQuery(TPointerOrReferenceParameterToConstQuery()) + TQueryCPP(TConstPackageQuery(TPointerOrReferenceParameterToConstQuery())) } Query constMemberFunctionReturnsNonConstPointerQuery() { //autogenerate `Query` type result = // `Query` type for `constMemberFunctionReturnsNonConstPointer` query - TConstPackageQuery(TConstMemberFunctionReturnsNonConstPointerQuery()) + TQueryCPP(TConstPackageQuery(TConstMemberFunctionReturnsNonConstPointerQuery())) } Query memberFunctionStaticIfPossibleQuery() { //autogenerate `Query` type result = // `Query` type for `memberFunctionStaticIfPossible` query - TConstPackageQuery(TMemberFunctionStaticIfPossibleQuery()) + TQueryCPP(TConstPackageQuery(TMemberFunctionStaticIfPossibleQuery())) } Query memberFunctionConstIfPossibleQuery() { //autogenerate `Query` type result = // `Query` type for `memberFunctionConstIfPossible` query - TConstPackageQuery(TMemberFunctionConstIfPossibleQuery()) + TQueryCPP(TConstPackageQuery(TMemberFunctionConstIfPossibleQuery())) } Query removeConstOrVolatileQualificationCertQuery() { //autogenerate `Query` type result = // `Query` type for `removeConstOrVolatileQualificationCert` query - TConstPackageQuery(TRemoveConstOrVolatileQualificationCertQuery()) + TQueryCPP(TConstPackageQuery(TRemoveConstOrVolatileQualificationCertQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/DeadCode.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/DeadCode.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode.qll index e5cb03cf86..d7b456252a 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/DeadCode.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/DeadCode.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype DeadCodeQuery = TUselessAssignmentQuery() or @@ -155,111 +156,111 @@ module DeadCodePackage { //autogenerate `Query` type result = // `Query` type for `uselessAssignment` query - TDeadCodePackageQuery(TUselessAssignmentQuery()) + TQueryCPP(TDeadCodePackageQuery(TUselessAssignmentQuery())) } Query unusedReturnValueQuery() { //autogenerate `Query` type result = // `Query` type for `unusedReturnValue` query - TDeadCodePackageQuery(TUnusedReturnValueQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedReturnValueQuery())) } Query unusedLocalFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `unusedLocalFunction` query - TDeadCodePackageQuery(TUnusedLocalFunctionQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedLocalFunctionQuery())) } Query unusedParameterQuery() { //autogenerate `Query` type result = // `Query` type for `unusedParameter` query - TDeadCodePackageQuery(TUnusedParameterQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedParameterQuery())) } Query unusedVirtualParameterQuery() { //autogenerate `Query` type result = // `Query` type for `unusedVirtualParameter` query - TDeadCodePackageQuery(TUnusedVirtualParameterQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedVirtualParameterQuery())) } Query unusedTypeDeclarationsQuery() { //autogenerate `Query` type result = // `Query` type for `unusedTypeDeclarations` query - TDeadCodePackageQuery(TUnusedTypeDeclarationsQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedTypeDeclarationsQuery())) } Query unreachableCodeQuery() { //autogenerate `Query` type result = // `Query` type for `unreachableCode` query - TDeadCodePackageQuery(TUnreachableCodeQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnreachableCodeQuery())) } Query unusedFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `unusedFunction` query - TDeadCodePackageQuery(TUnusedFunctionQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedFunctionQuery())) } Query infeasiblePathQuery() { //autogenerate `Query` type result = // `Query` type for `infeasiblePath` query - TDeadCodePackageQuery(TInfeasiblePathQuery()) + TQueryCPP(TDeadCodePackageQuery(TInfeasiblePathQuery())) } Query unusedLocalVariableQuery() { //autogenerate `Query` type result = // `Query` type for `unusedLocalVariable` query - TDeadCodePackageQuery(TUnusedLocalVariableQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedLocalVariableQuery())) } Query unusedGlobalOrNamespaceVariableQuery() { //autogenerate `Query` type result = // `Query` type for `unusedGlobalOrNamespaceVariable` query - TDeadCodePackageQuery(TUnusedGlobalOrNamespaceVariableQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedGlobalOrNamespaceVariableQuery())) } Query unusedMemberVariableQuery() { //autogenerate `Query` type result = // `Query` type for `unusedMemberVariable` query - TDeadCodePackageQuery(TUnusedMemberVariableQuery()) + TQueryCPP(TDeadCodePackageQuery(TUnusedMemberVariableQuery())) } Query singleUseLocalPODVariableQuery() { //autogenerate `Query` type result = // `Query` type for `singleUseLocalPODVariable` query - TDeadCodePackageQuery(TSingleUseLocalPODVariableQuery()) + TQueryCPP(TDeadCodePackageQuery(TSingleUseLocalPODVariableQuery())) } Query singleUseGlobalOrNamespacePODVariableQuery() { //autogenerate `Query` type result = // `Query` type for `singleUseGlobalOrNamespacePODVariable` query - TDeadCodePackageQuery(TSingleUseGlobalOrNamespacePODVariableQuery()) + TQueryCPP(TDeadCodePackageQuery(TSingleUseGlobalOrNamespacePODVariableQuery())) } Query singleUseMemberPODVariableQuery() { //autogenerate `Query` type result = // `Query` type for `singleUseMemberPODVariable` query - TDeadCodePackageQuery(TSingleUseMemberPODVariableQuery()) + TQueryCPP(TDeadCodePackageQuery(TSingleUseMemberPODVariableQuery())) } Query deadCodeQuery() { //autogenerate `Query` type result = // `Query` type for `deadCode` query - TDeadCodePackageQuery(TDeadCodeQuery()) + TQueryCPP(TDeadCodePackageQuery(TDeadCodeQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Declarations.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Declarations.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Declarations.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Declarations.qll index 9a03c50716..c8fc673e36 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Declarations.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Declarations.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype DeclarationsQuery = TOperatorNewAndOperatorDeleteNotDefinedLocallyQuery() or @@ -164,118 +165,118 @@ module DeclarationsPackage { //autogenerate `Query` type result = // `Query` type for `operatorNewAndOperatorDeleteNotDefinedLocally` query - TDeclarationsPackageQuery(TOperatorNewAndOperatorDeleteNotDefinedLocallyQuery()) + TQueryCPP(TDeclarationsPackageQuery(TOperatorNewAndOperatorDeleteNotDefinedLocallyQuery())) } Query operatorNewAndOperatorDeleteNotDefinedGloballyQuery() { //autogenerate `Query` type result = // `Query` type for `operatorNewAndOperatorDeleteNotDefinedGlobally` query - TDeclarationsPackageQuery(TOperatorNewAndOperatorDeleteNotDefinedGloballyQuery()) + TQueryCPP(TDeclarationsPackageQuery(TOperatorNewAndOperatorDeleteNotDefinedGloballyQuery())) } Query globalSizedOperatorDeleteNotDefinedQuery() { //autogenerate `Query` type result = // `Query` type for `globalSizedOperatorDeleteNotDefined` query - TDeclarationsPackageQuery(TGlobalSizedOperatorDeleteNotDefinedQuery()) + TQueryCPP(TDeclarationsPackageQuery(TGlobalSizedOperatorDeleteNotDefinedQuery())) } Query globalUnsizedOperatorDeleteNotDefinedQuery() { //autogenerate `Query` type result = // `Query` type for `globalUnsizedOperatorDeleteNotDefined` query - TDeclarationsPackageQuery(TGlobalUnsizedOperatorDeleteNotDefinedQuery()) + TQueryCPP(TDeclarationsPackageQuery(TGlobalUnsizedOperatorDeleteNotDefinedQuery())) } Query variableWidthIntegerTypesUsedQuery() { //autogenerate `Query` type result = // `Query` type for `variableWidthIntegerTypesUsed` query - TDeclarationsPackageQuery(TVariableWidthIntegerTypesUsedQuery()) + TQueryCPP(TDeclarationsPackageQuery(TVariableWidthIntegerTypesUsedQuery())) } Query autoSpecifierNotUsedAppropriatelyInFunctionDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `autoSpecifierNotUsedAppropriatelyInFunctionDefinition` query - TDeclarationsPackageQuery(TAutoSpecifierNotUsedAppropriatelyInFunctionDefinitionQuery()) + TQueryCPP(TDeclarationsPackageQuery(TAutoSpecifierNotUsedAppropriatelyInFunctionDefinitionQuery())) } Query autoSpecifierNotUsedAppropriatelyInVariableDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `autoSpecifierNotUsedAppropriatelyInVariableDefinition` query - TDeclarationsPackageQuery(TAutoSpecifierNotUsedAppropriatelyInVariableDefinitionQuery()) + TQueryCPP(TDeclarationsPackageQuery(TAutoSpecifierNotUsedAppropriatelyInVariableDefinitionQuery())) } Query identifierDeclarationAndInitializationNotOnSeparateLinesQuery() { //autogenerate `Query` type result = // `Query` type for `identifierDeclarationAndInitializationNotOnSeparateLines` query - TDeclarationsPackageQuery(TIdentifierDeclarationAndInitializationNotOnSeparateLinesQuery()) + TQueryCPP(TDeclarationsPackageQuery(TIdentifierDeclarationAndInitializationNotOnSeparateLinesQuery())) } Query classStructEnumDeclaredInDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `classStructEnumDeclaredInDefinition` query - TDeclarationsPackageQuery(TClassStructEnumDeclaredInDefinitionQuery()) + TQueryCPP(TDeclarationsPackageQuery(TClassStructEnumDeclaredInDefinitionQuery())) } Query enumerationUnderlyingBaseTypeNotExplicitlyDefinedQuery() { //autogenerate `Query` type result = // `Query` type for `enumerationUnderlyingBaseTypeNotExplicitlyDefined` query - TDeclarationsPackageQuery(TEnumerationUnderlyingBaseTypeNotExplicitlyDefinedQuery()) + TQueryCPP(TDeclarationsPackageQuery(TEnumerationUnderlyingBaseTypeNotExplicitlyDefinedQuery())) } Query enumerationsNotDeclaredAsScopedEnumClassesQuery() { //autogenerate `Query` type result = // `Query` type for `enumerationsNotDeclaredAsScopedEnumClasses` query - TDeclarationsPackageQuery(TEnumerationsNotDeclaredAsScopedEnumClassesQuery()) + TQueryCPP(TDeclarationsPackageQuery(TEnumerationsNotDeclaredAsScopedEnumClassesQuery())) } Query noneFirstOrAllEnumeratorsNotInitializedQuery() { //autogenerate `Query` type result = // `Query` type for `noneFirstOrAllEnumeratorsNotInitialized` query - TDeclarationsPackageQuery(TNoneFirstOrAllEnumeratorsNotInitializedQuery()) + TQueryCPP(TDeclarationsPackageQuery(TNoneFirstOrAllEnumeratorsNotInitializedQuery())) } Query functionsDeclaredAtBlockScopeQuery() { //autogenerate `Query` type result = // `Query` type for `functionsDeclaredAtBlockScope` query - TDeclarationsPackageQuery(TFunctionsDeclaredAtBlockScopeQuery()) + TQueryCPP(TDeclarationsPackageQuery(TFunctionsDeclaredAtBlockScopeQuery())) } Query declarationsOfAnObjectShallHaveCompatibleTypesQuery() { //autogenerate `Query` type result = // `Query` type for `declarationsOfAnObjectShallHaveCompatibleTypes` query - TDeclarationsPackageQuery(TDeclarationsOfAnObjectShallHaveCompatibleTypesQuery()) + TQueryCPP(TDeclarationsPackageQuery(TDeclarationsOfAnObjectShallHaveCompatibleTypesQuery())) } Query declarationsOfAFunctionShallHaveCompatibleTypesQuery() { //autogenerate `Query` type result = // `Query` type for `declarationsOfAFunctionShallHaveCompatibleTypes` query - TDeclarationsPackageQuery(TDeclarationsOfAFunctionShallHaveCompatibleTypesQuery()) + TQueryCPP(TDeclarationsPackageQuery(TDeclarationsOfAFunctionShallHaveCompatibleTypesQuery())) } Query typesNotIdenticalInObjectDeclarationsQuery() { //autogenerate `Query` type result = // `Query` type for `typesNotIdenticalInObjectDeclarations` query - TDeclarationsPackageQuery(TTypesNotIdenticalInObjectDeclarationsQuery()) + TQueryCPP(TDeclarationsPackageQuery(TTypesNotIdenticalInObjectDeclarationsQuery())) } Query typesNotIdenticalInReturnDeclarationsQuery() { //autogenerate `Query` type result = // `Query` type for `typesNotIdenticalInReturnDeclarations` query - TDeclarationsPackageQuery(TTypesNotIdenticalInReturnDeclarationsQuery()) + TQueryCPP(TDeclarationsPackageQuery(TTypesNotIdenticalInReturnDeclarationsQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/ExceptionSafety.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/ExceptionSafety.qll similarity index 83% rename from cpp/common/src/codingstandards/cpp/exclusions/ExceptionSafety.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/ExceptionSafety.qll index 569b0b4a7a..7611aad062 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/ExceptionSafety.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/ExceptionSafety.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ExceptionSafetyQuery = TExceptionSafetyGuaranteesNotProvidedQuery() or @@ -56,34 +57,34 @@ module ExceptionSafetyPackage { //autogenerate `Query` type result = // `Query` type for `exceptionSafetyGuaranteesNotProvided` query - TExceptionSafetyPackageQuery(TExceptionSafetyGuaranteesNotProvidedQuery()) + TQueryCPP(TExceptionSafetyPackageQuery(TExceptionSafetyGuaranteesNotProvidedQuery())) } Query exceptionSafetyGuaranteeOfACalledFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `exceptionSafetyGuaranteeOfACalledFunction` query - TExceptionSafetyPackageQuery(TExceptionSafetyGuaranteeOfACalledFunctionQuery()) + TQueryCPP(TExceptionSafetyPackageQuery(TExceptionSafetyGuaranteeOfACalledFunctionQuery())) } Query validResourcesStateBeforeThrowQuery() { //autogenerate `Query` type result = // `Query` type for `validResourcesStateBeforeThrow` query - TExceptionSafetyPackageQuery(TValidResourcesStateBeforeThrowQuery()) + TQueryCPP(TExceptionSafetyPackageQuery(TValidResourcesStateBeforeThrowQuery())) } Query guaranteeExceptionSafetyQuery() { //autogenerate `Query` type result = // `Query` type for `guaranteeExceptionSafety` query - TExceptionSafetyPackageQuery(TGuaranteeExceptionSafetyQuery()) + TQueryCPP(TExceptionSafetyPackageQuery(TGuaranteeExceptionSafetyQuery())) } Query doNotLeakResourcesWhenHandlingExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotLeakResourcesWhenHandlingExceptions` query - TExceptionSafetyPackageQuery(TDoNotLeakResourcesWhenHandlingExceptionsQuery()) + TQueryCPP(TExceptionSafetyPackageQuery(TDoNotLeakResourcesWhenHandlingExceptionsQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Exceptions1.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Exceptions1.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Exceptions1.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Exceptions1.qll index ef82a92eaf..fc77c5e011 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Exceptions1.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Exceptions1.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype Exceptions1Query = TExceptionThrownOnCompletionQuery() or @@ -317,237 +318,237 @@ module Exceptions1Package { //autogenerate `Query` type result = // `Query` type for `exceptionThrownOnCompletion` query - TExceptions1PackageQuery(TExceptionThrownOnCompletionQuery()) + TQueryCPP(TExceptions1PackageQuery(TExceptionThrownOnCompletionQuery())) } Query recoverableUncheckedExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `recoverableUncheckedExceptions` query - TExceptions1PackageQuery(TRecoverableUncheckedExceptionsQuery()) + TQueryCPP(TExceptions1PackageQuery(TRecoverableUncheckedExceptionsQuery())) } Query unrecoverableCheckedExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `unrecoverableCheckedExceptions` query - TExceptions1PackageQuery(TUnrecoverableCheckedExceptionsQuery()) + TQueryCPP(TExceptions1PackageQuery(TUnrecoverableCheckedExceptionsQuery())) } Query pointerExceptionObjectQuery() { //autogenerate `Query` type result = // `Query` type for `pointerExceptionObject` query - TExceptions1PackageQuery(TPointerExceptionObjectQuery()) + TQueryCPP(TExceptions1PackageQuery(TPointerExceptionObjectQuery())) } Query thrownExceptionsShouldBeUniqueQuery() { //autogenerate `Query` type result = // `Query` type for `thrownExceptionsShouldBeUnique` query - TExceptions1PackageQuery(TThrownExceptionsShouldBeUniqueQuery()) + TQueryCPP(TExceptions1PackageQuery(TThrownExceptionsShouldBeUniqueQuery())) } Query constructorsThatAreNotNoexceptInvokedBeforeProgramStartupQuery() { //autogenerate `Query` type result = // `Query` type for `constructorsThatAreNotNoexceptInvokedBeforeProgramStartup` query - TExceptions1PackageQuery(TConstructorsThatAreNotNoexceptInvokedBeforeProgramStartupQuery()) + TQueryCPP(TExceptions1PackageQuery(TConstructorsThatAreNotNoexceptInvokedBeforeProgramStartupQuery())) } Query missingCatchHandlerInMainQuery() { //autogenerate `Query` type result = // `Query` type for `missingCatchHandlerInMain` query - TExceptions1PackageQuery(TMissingCatchHandlerInMainQuery()) + TQueryCPP(TExceptions1PackageQuery(TMissingCatchHandlerInMainQuery())) } Query catchAllEllipsisUsedInNonMainQuery() { //autogenerate `Query` type result = // `Query` type for `catchAllEllipsisUsedInNonMain` query - TExceptions1PackageQuery(TCatchAllEllipsisUsedInNonMainQuery()) + TQueryCPP(TExceptions1PackageQuery(TCatchAllEllipsisUsedInNonMainQuery())) } Query useOfDynamicExceptionSpecificationQuery() { //autogenerate `Query` type result = // `Query` type for `useOfDynamicExceptionSpecification` query - TExceptions1PackageQuery(TUseOfDynamicExceptionSpecificationQuery()) + TQueryCPP(TExceptions1PackageQuery(TUseOfDynamicExceptionSpecificationQuery())) } Query noExceptFunctionThrowsQuery() { //autogenerate `Query` type result = // `Query` type for `noExceptFunctionThrows` query - TExceptions1PackageQuery(TNoExceptFunctionThrowsQuery()) + TQueryCPP(TExceptions1PackageQuery(TNoExceptFunctionThrowsQuery())) } Query missingNoExceptQuery() { //autogenerate `Query` type result = // `Query` type for `missingNoExcept` query - TExceptions1PackageQuery(TMissingNoExceptQuery()) + TQueryCPP(TExceptions1PackageQuery(TMissingNoExceptQuery())) } Query explicitAbruptTerminationAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `explicitAbruptTerminationAutosar` query - TExceptions1PackageQuery(TExplicitAbruptTerminationAutosarQuery()) + TQueryCPP(TExceptions1PackageQuery(TExplicitAbruptTerminationAutosarQuery())) } Query conditionVariablePostConditionFailedAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `conditionVariablePostConditionFailedAutosar` query - TExceptions1PackageQuery(TConditionVariablePostConditionFailedAutosarQuery()) + TQueryCPP(TExceptions1PackageQuery(TConditionVariablePostConditionFailedAutosarQuery())) } Query joinableThreadCopiedOrDestroyedAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `joinableThreadCopiedOrDestroyedAutosar` query - TExceptions1PackageQuery(TJoinableThreadCopiedOrDestroyedAutosarQuery()) + TQueryCPP(TExceptions1PackageQuery(TJoinableThreadCopiedOrDestroyedAutosarQuery())) } Query rethrowNestedWithoutCaptureAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `rethrowNestedWithoutCaptureAutosar` query - TExceptions1PackageQuery(TRethrowNestedWithoutCaptureAutosarQuery()) + TQueryCPP(TExceptions1PackageQuery(TRethrowNestedWithoutCaptureAutosarQuery())) } Query exitHandlerThrowsExceptionAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `exitHandlerThrowsExceptionAutosar` query - TExceptions1PackageQuery(TExitHandlerThrowsExceptionAutosarQuery()) + TQueryCPP(TExceptions1PackageQuery(TExitHandlerThrowsExceptionAutosarQuery())) } Query gotoToCatchBlockQuery() { //autogenerate `Query` type result = // `Query` type for `gotoToCatchBlock` query - TExceptions1PackageQuery(TGotoToCatchBlockQuery()) + TQueryCPP(TExceptions1PackageQuery(TGotoToCatchBlockQuery())) } Query switchToCatchBlockQuery() { //autogenerate `Query` type result = // `Query` type for `switchToCatchBlock` query - TExceptions1PackageQuery(TSwitchToCatchBlockQuery()) + TQueryCPP(TExceptions1PackageQuery(TSwitchToCatchBlockQuery())) } Query exceptionThrownDuringThrowQuery() { //autogenerate `Query` type result = // `Query` type for `exceptionThrownDuringThrow` query - TExceptions1PackageQuery(TExceptionThrownDuringThrowQuery()) + TQueryCPP(TExceptions1PackageQuery(TExceptionThrownDuringThrowQuery())) } Query nullThrownExplicitlyQuery() { //autogenerate `Query` type result = // `Query` type for `nullThrownExplicitly` query - TExceptions1PackageQuery(TNullThrownExplicitlyQuery()) + TQueryCPP(TExceptions1PackageQuery(TNullThrownExplicitlyQuery())) } Query emptyThrowOutsideCatchQuery() { //autogenerate `Query` type result = // `Query` type for `emptyThrowOutsideCatch` query - TExceptions1PackageQuery(TEmptyThrowOutsideCatchQuery()) + TQueryCPP(TExceptions1PackageQuery(TEmptyThrowOutsideCatchQuery())) } Query catchAllExplicitlyThrownExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `catchAllExplicitlyThrownExceptions` query - TExceptions1PackageQuery(TCatchAllExplicitlyThrownExceptionsQuery()) + TQueryCPP(TExceptions1PackageQuery(TCatchAllExplicitlyThrownExceptionsQuery())) } Query catchAllHandlerLastQuery() { //autogenerate `Query` type result = // `Query` type for `catchAllHandlerLast` query - TExceptions1PackageQuery(TCatchAllHandlerLastQuery()) + TQueryCPP(TExceptions1PackageQuery(TCatchAllHandlerLastQuery())) } Query conditionVariablePostConditionFailedCertQuery() { //autogenerate `Query` type result = // `Query` type for `conditionVariablePostConditionFailedCert` query - TExceptions1PackageQuery(TConditionVariablePostConditionFailedCertQuery()) + TQueryCPP(TExceptions1PackageQuery(TConditionVariablePostConditionFailedCertQuery())) } Query joinableThreadCopiedOrDestroyedCertQuery() { //autogenerate `Query` type result = // `Query` type for `joinableThreadCopiedOrDestroyedCert` query - TExceptions1PackageQuery(TJoinableThreadCopiedOrDestroyedCertQuery()) + TQueryCPP(TExceptions1PackageQuery(TJoinableThreadCopiedOrDestroyedCertQuery())) } Query rethrowNestedWithoutCaptureCertQuery() { //autogenerate `Query` type result = // `Query` type for `rethrowNestedWithoutCaptureCert` query - TExceptions1PackageQuery(TRethrowNestedWithoutCaptureCertQuery()) + TQueryCPP(TExceptions1PackageQuery(TRethrowNestedWithoutCaptureCertQuery())) } Query explicitAbruptTerminationCertQuery() { //autogenerate `Query` type result = // `Query` type for `explicitAbruptTerminationCert` query - TExceptions1PackageQuery(TExplicitAbruptTerminationCertQuery()) + TQueryCPP(TExceptions1PackageQuery(TExplicitAbruptTerminationCertQuery())) } Query exitHandlerThrowsExceptionCertQuery() { //autogenerate `Query` type result = // `Query` type for `exitHandlerThrowsExceptionCert` query - TExceptions1PackageQuery(TExitHandlerThrowsExceptionCertQuery()) + TQueryCPP(TExceptions1PackageQuery(TExitHandlerThrowsExceptionCertQuery())) } Query handleAllExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `handleAllExceptions` query - TExceptions1PackageQuery(THandleAllExceptionsQuery()) + TQueryCPP(TExceptions1PackageQuery(THandleAllExceptionsQuery())) } Query destroyedValueReferencedInConstructorDestructorCatchBlockQuery() { //autogenerate `Query` type result = // `Query` type for `destroyedValueReferencedInConstructorDestructorCatchBlock` query - TExceptions1PackageQuery(TDestroyedValueReferencedInConstructorDestructorCatchBlockQuery()) + TQueryCPP(TExceptions1PackageQuery(TDestroyedValueReferencedInConstructorDestructorCatchBlockQuery())) } Query honorExceptionSpecificationsQuery() { //autogenerate `Query` type result = // `Query` type for `honorExceptionSpecifications` query - TExceptions1PackageQuery(THonorExceptionSpecificationsQuery()) + TQueryCPP(TExceptions1PackageQuery(THonorExceptionSpecificationsQuery())) } Query handleAllExceptionsThrownBeforeMainBeginsExecutingQuery() { //autogenerate `Query` type result = // `Query` type for `handleAllExceptionsThrownBeforeMainBeginsExecuting` query - TExceptions1PackageQuery(THandleAllExceptionsThrownBeforeMainBeginsExecutingQuery()) + TQueryCPP(TExceptions1PackageQuery(THandleAllExceptionsThrownBeforeMainBeginsExecutingQuery())) } Query exceptionObjectsMustBeNothrowCopyConstructibleQuery() { //autogenerate `Query` type result = // `Query` type for `exceptionObjectsMustBeNothrowCopyConstructible` query - TExceptions1PackageQuery(TExceptionObjectsMustBeNothrowCopyConstructibleQuery()) + TQueryCPP(TExceptions1PackageQuery(TExceptionObjectsMustBeNothrowCopyConstructibleQuery())) } Query catchExceptionsByLvalueReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `catchExceptionsByLvalueReference` query - TExceptions1PackageQuery(TCatchExceptionsByLvalueReferenceQuery()) + TQueryCPP(TExceptions1PackageQuery(TCatchExceptionsByLvalueReferenceQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Exceptions2.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Exceptions2.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Exceptions2.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Exceptions2.qll index 4bb82bbbea..6e0a3e1f2b 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Exceptions2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Exceptions2.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype Exceptions2Query = TOnlyThrowStdExceptionDerivedTypesQuery() or @@ -164,118 +165,118 @@ module Exceptions2Package { //autogenerate `Query` type result = // `Query` type for `onlyThrowStdExceptionDerivedTypes` query - TExceptions2PackageQuery(TOnlyThrowStdExceptionDerivedTypesQuery()) + TQueryCPP(TExceptions2PackageQuery(TOnlyThrowStdExceptionDerivedTypesQuery())) } Query constructorErrorLeavesObjectInInvalidStateQuery() { //autogenerate `Query` type result = // `Query` type for `constructorErrorLeavesObjectInInvalidState` query - TExceptions2PackageQuery(TConstructorErrorLeavesObjectInInvalidStateQuery()) + TQueryCPP(TExceptions2PackageQuery(TConstructorErrorLeavesObjectInInvalidStateQuery())) } Query classTypeExceptionNotCaughtByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `classTypeExceptionNotCaughtByReference` query - TExceptions2PackageQuery(TClassTypeExceptionNotCaughtByReferenceQuery()) + TQueryCPP(TExceptions2PackageQuery(TClassTypeExceptionNotCaughtByReferenceQuery())) } Query incompatibleNoexceptSpecificationQuery() { //autogenerate `Query` type result = // `Query` type for `incompatibleNoexceptSpecification` query - TExceptions2PackageQuery(TIncompatibleNoexceptSpecificationQuery()) + TQueryCPP(TExceptions2PackageQuery(TIncompatibleNoexceptSpecificationQuery())) } Query inconsistentNoexceptFalseSpecificationQuery() { //autogenerate `Query` type result = // `Query` type for `inconsistentNoexceptFalseSpecification` query - TExceptions2PackageQuery(TInconsistentNoexceptFalseSpecificationQuery()) + TQueryCPP(TExceptions2PackageQuery(TInconsistentNoexceptFalseSpecificationQuery())) } Query inconsistentNoexceptTrueSpecificationQuery() { //autogenerate `Query` type result = // `Query` type for `inconsistentNoexceptTrueSpecification` query - TExceptions2PackageQuery(TInconsistentNoexceptTrueSpecificationQuery()) + TQueryCPP(TExceptions2PackageQuery(TInconsistentNoexceptTrueSpecificationQuery())) } Query incompatibleNoexceptSpecificationForOverridersQuery() { //autogenerate `Query` type result = // `Query` type for `incompatibleNoexceptSpecificationForOverriders` query - TExceptions2PackageQuery(TIncompatibleNoexceptSpecificationForOverridersQuery()) + TQueryCPP(TExceptions2PackageQuery(TIncompatibleNoexceptSpecificationForOverridersQuery())) } Query missingCheckedExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `missingCheckedExceptions` query - TExceptions2PackageQuery(TMissingCheckedExceptionsQuery()) + TQueryCPP(TExceptions2PackageQuery(TMissingCheckedExceptionsQuery())) } Query inconsistentCheckedExceptionsQuery() { //autogenerate `Query` type result = // `Query` type for `inconsistentCheckedExceptions` query - TExceptions2PackageQuery(TInconsistentCheckedExceptionsQuery()) + TQueryCPP(TExceptions2PackageQuery(TInconsistentCheckedExceptionsQuery())) } Query specialFunctionExitsWithExceptionQuery() { //autogenerate `Query` type result = // `Query` type for `specialFunctionExitsWithException` query - TExceptions2PackageQuery(TSpecialFunctionExitsWithExceptionQuery()) + TQueryCPP(TExceptions2PackageQuery(TSpecialFunctionExitsWithExceptionQuery())) } Query specialFunctionMissingNoExceptSpecificationQuery() { //autogenerate `Query` type result = // `Query` type for `specialFunctionMissingNoExceptSpecification` query - TExceptions2PackageQuery(TSpecialFunctionMissingNoExceptSpecificationQuery()) + TQueryCPP(TExceptions2PackageQuery(TSpecialFunctionMissingNoExceptSpecificationQuery())) } Query exceptionRaisedDuringStartupQuery() { //autogenerate `Query` type result = // `Query` type for `exceptionRaisedDuringStartup` query - TExceptions2PackageQuery(TExceptionRaisedDuringStartupQuery()) + TQueryCPP(TExceptions2PackageQuery(TExceptionRaisedDuringStartupQuery())) } Query exceptionRaisedDuringTerminationQuery() { //autogenerate `Query` type result = // `Query` type for `exceptionRaisedDuringTermination` query - TExceptions2PackageQuery(TExceptionRaisedDuringTerminationQuery()) + TQueryCPP(TExceptions2PackageQuery(TExceptionRaisedDuringTerminationQuery())) } Query destroyedValueReferencedInDestructorCatchBlockQuery() { //autogenerate `Query` type result = // `Query` type for `destroyedValueReferencedInDestructorCatchBlock` query - TExceptions2PackageQuery(TDestroyedValueReferencedInDestructorCatchBlockQuery()) + TQueryCPP(TExceptions2PackageQuery(TDestroyedValueReferencedInDestructorCatchBlockQuery())) } Query catchBlockShadowingMisraQuery() { //autogenerate `Query` type result = // `Query` type for `catchBlockShadowingMisra` query - TExceptions2PackageQuery(TCatchBlockShadowingMisraQuery()) + TQueryCPP(TExceptions2PackageQuery(TCatchBlockShadowingMisraQuery())) } Query doNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctionsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctions` query - TExceptions2PackageQuery(TDoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctionsQuery()) + TQueryCPP(TExceptions2PackageQuery(TDoNotLetExceptionsEscapeFromDestructorsOrDeallocationFunctionsQuery())) } Query catchBlockShadowingCertQuery() { //autogenerate `Query` type result = // `Query` type for `catchBlockShadowingCert` query - TExceptions2PackageQuery(TCatchBlockShadowingCertQuery()) + TQueryCPP(TExceptions2PackageQuery(TCatchBlockShadowingCertQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Expressions.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Expressions.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Expressions.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Expressions.qll index 7e82d6bb1c..049209d3fa 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Expressions.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Expressions.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ExpressionsQuery = TOperationsAssumingMemoryLayoutPerformedOnObjectsQuery() or @@ -155,111 +156,111 @@ module ExpressionsPackage { //autogenerate `Query` type result = // `Query` type for `operationsAssumingMemoryLayoutPerformedOnObjects` query - TExpressionsPackageQuery(TOperationsAssumingMemoryLayoutPerformedOnObjectsQuery()) + TQueryCPP(TExpressionsPackageQuery(TOperationsAssumingMemoryLayoutPerformedOnObjectsQuery())) } Query enumUsedInArithmeticContextsQuery() { //autogenerate `Query` type result = // `Query` type for `enumUsedInArithmeticContexts` query - TExpressionsPackageQuery(TEnumUsedInArithmeticContextsQuery()) + TQueryCPP(TExpressionsPackageQuery(TEnumUsedInArithmeticContextsQuery())) } Query divisorEqualToZeroQuery() { //autogenerate `Query` type result = // `Query` type for `divisorEqualToZero` query - TExpressionsPackageQuery(TDivisorEqualToZeroQuery()) + TQueryCPP(TExpressionsPackageQuery(TDivisorEqualToZeroQuery())) } Query functionErroneousReturnValueNotTestedQuery() { //autogenerate `Query` type result = // `Query` type for `functionErroneousReturnValueNotTested` query - TExpressionsPackageQuery(TFunctionErroneousReturnValueNotTestedQuery()) + TQueryCPP(TExpressionsPackageQuery(TFunctionErroneousReturnValueNotTestedQuery())) } Query boolOperandsToDisallowedBuiltInOperatorsQuery() { //autogenerate `Query` type result = // `Query` type for `boolOperandsToDisallowedBuiltInOperators` query - TExpressionsPackageQuery(TBoolOperandsToDisallowedBuiltInOperatorsQuery()) + TQueryCPP(TExpressionsPackageQuery(TBoolOperandsToDisallowedBuiltInOperatorsQuery())) } Query charUsedAsOperandsToDisallowedBuiltInOperatorsQuery() { //autogenerate `Query` type result = // `Query` type for `charUsedAsOperandsToDisallowedBuiltInOperators` query - TExpressionsPackageQuery(TCharUsedAsOperandsToDisallowedBuiltInOperatorsQuery()) + TQueryCPP(TExpressionsPackageQuery(TCharUsedAsOperandsToDisallowedBuiltInOperatorsQuery())) } Query ternaryOperatorConditionNotTypeBoolQuery() { //autogenerate `Query` type result = // `Query` type for `ternaryOperatorConditionNotTypeBool` query - TExpressionsPackageQuery(TTernaryOperatorConditionNotTypeBoolQuery()) + TQueryCPP(TExpressionsPackageQuery(TTernaryOperatorConditionNotTypeBoolQuery())) } Query bitwiseOperatorOperandsHaveDifferentUnderlyingTypeQuery() { //autogenerate `Query` type result = // `Query` type for `bitwiseOperatorOperandsHaveDifferentUnderlyingType` query - TExpressionsPackageQuery(TBitwiseOperatorOperandsHaveDifferentUnderlyingTypeQuery()) + TQueryCPP(TExpressionsPackageQuery(TBitwiseOperatorOperandsHaveDifferentUnderlyingTypeQuery())) } Query bitwiseOperatorAppliedToSignedTypesQuery() { //autogenerate `Query` type result = // `Query` type for `bitwiseOperatorAppliedToSignedTypes` query - TExpressionsPackageQuery(TBitwiseOperatorAppliedToSignedTypesQuery()) + TQueryCPP(TExpressionsPackageQuery(TBitwiseOperatorAppliedToSignedTypesQuery())) } Query cvalueExpressionConvertedToDifferentUnderlyingTypeQuery() { //autogenerate `Query` type result = // `Query` type for `cvalueExpressionConvertedToDifferentUnderlyingType` query - TExpressionsPackageQuery(TCvalueExpressionConvertedToDifferentUnderlyingTypeQuery()) + TQueryCPP(TExpressionsPackageQuery(TCvalueExpressionConvertedToDifferentUnderlyingTypeQuery())) } Query constantUnsignedIntegerExpressionsWrapAroundQuery() { //autogenerate `Query` type result = // `Query` type for `constantUnsignedIntegerExpressionsWrapAround` query - TExpressionsPackageQuery(TConstantUnsignedIntegerExpressionsWrapAroundQuery()) + TQueryCPP(TExpressionsPackageQuery(TConstantUnsignedIntegerExpressionsWrapAroundQuery())) } Query rightBitShiftOperandIsNegativeOrTooWideQuery() { //autogenerate `Query` type result = // `Query` type for `rightBitShiftOperandIsNegativeOrTooWide` query - TExpressionsPackageQuery(TRightBitShiftOperandIsNegativeOrTooWideQuery()) + TQueryCPP(TExpressionsPackageQuery(TRightBitShiftOperandIsNegativeOrTooWideQuery())) } Query floatsTestedForEqualityQuery() { //autogenerate `Query` type result = // `Query` type for `floatsTestedForEquality` query - TExpressionsPackageQuery(TFloatsTestedForEqualityQuery()) + TQueryCPP(TExpressionsPackageQuery(TFloatsTestedForEqualityQuery())) } Query passPromotablePrimitiveTypeToVaStartQuery() { //autogenerate `Query` type result = // `Query` type for `passPromotablePrimitiveTypeToVaStart` query - TExpressionsPackageQuery(TPassPromotablePrimitiveTypeToVaStartQuery()) + TQueryCPP(TExpressionsPackageQuery(TPassPromotablePrimitiveTypeToVaStartQuery())) } Query passReferenceTypeToVaStartQuery() { //autogenerate `Query` type result = // `Query` type for `passReferenceTypeToVaStart` query - TExpressionsPackageQuery(TPassReferenceTypeToVaStartQuery()) + TQueryCPP(TExpressionsPackageQuery(TPassReferenceTypeToVaStartQuery())) } Query passNonTrivialObjectToVaStartQuery() { //autogenerate `Query` type result = // `Query` type for `passNonTrivialObjectToVaStart` query - TExpressionsPackageQuery(TPassNonTrivialObjectToVaStartQuery()) + TQueryCPP(TExpressionsPackageQuery(TPassNonTrivialObjectToVaStartQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Freed.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Freed.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Freed.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Freed.qll index a494aa2c96..a7122cb236 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Freed.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Freed.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype FreedQuery = TNewDeleteArrayMismatchQuery() or @@ -92,62 +93,62 @@ module FreedPackage { //autogenerate `Query` type result = // `Query` type for `newDeleteArrayMismatch` query - TFreedPackageQuery(TNewDeleteArrayMismatchQuery()) + TQueryCPP(TFreedPackageQuery(TNewDeleteArrayMismatchQuery())) } Query newArrayDeleteMismatchQuery() { //autogenerate `Query` type result = // `Query` type for `newArrayDeleteMismatch` query - TFreedPackageQuery(TNewArrayDeleteMismatchQuery()) + TQueryCPP(TFreedPackageQuery(TNewArrayDeleteMismatchQuery())) } Query objectAccessedBeforeLifetimeAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `objectAccessedBeforeLifetimeAutosar` query - TFreedPackageQuery(TObjectAccessedBeforeLifetimeAutosarQuery()) + TQueryCPP(TFreedPackageQuery(TObjectAccessedBeforeLifetimeAutosarQuery())) } Query objectAccessedAfterLifetimeAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `objectAccessedAfterLifetimeAutosar` query - TFreedPackageQuery(TObjectAccessedAfterLifetimeAutosarQuery()) + TQueryCPP(TFreedPackageQuery(TObjectAccessedAfterLifetimeAutosarQuery())) } Query assignmentOfEscapingAutoStorageQuery() { //autogenerate `Query` type result = // `Query` type for `assignmentOfEscapingAutoStorage` query - TFreedPackageQuery(TAssignmentOfEscapingAutoStorageQuery()) + TQueryCPP(TFreedPackageQuery(TAssignmentOfEscapingAutoStorageQuery())) } Query doNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeQuery() { //autogenerate `Query` type result = // `Query` type for `doNotDeleteAnArrayThroughAPointerOfTheIncorrectType` query - TFreedPackageQuery(TDoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeQuery()) + TQueryCPP(TFreedPackageQuery(TDoNotDeleteAnArrayThroughAPointerOfTheIncorrectTypeQuery())) } Query objectAccessedBeforeLifetimeCertQuery() { //autogenerate `Query` type result = // `Query` type for `objectAccessedBeforeLifetimeCert` query - TFreedPackageQuery(TObjectAccessedBeforeLifetimeCertQuery()) + TQueryCPP(TFreedPackageQuery(TObjectAccessedBeforeLifetimeCertQuery())) } Query objectAccessedAfterLifetimeCertQuery() { //autogenerate `Query` type result = // `Query` type for `objectAccessedAfterLifetimeCert` query - TFreedPackageQuery(TObjectAccessedAfterLifetimeCertQuery()) + TQueryCPP(TFreedPackageQuery(TObjectAccessedAfterLifetimeCertQuery())) } Query useAfterFreeQuery() { //autogenerate `Query` type result = // `Query` type for `useAfterFree` query - TFreedPackageQuery(TUseAfterFreeQuery()) + TQueryCPP(TFreedPackageQuery(TUseAfterFreeQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Functions.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Functions.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Functions.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Functions.qll index 2ec486455d..73ef5a2ea3 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Functions.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Functions.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype FunctionsQuery = TCStandardLibraryFunctionCallsQuery() or @@ -137,97 +138,97 @@ module FunctionsPackage { //autogenerate `Query` type result = // `Query` type for `cStandardLibraryFunctionCalls` query - TFunctionsPackageQuery(TCStandardLibraryFunctionCallsQuery()) + TQueryCPP(TFunctionsPackageQuery(TCStandardLibraryFunctionCallsQuery())) } Query trivialAccessorAndMutatorFunctionsNotInlinedQuery() { //autogenerate `Query` type result = // `Query` type for `trivialAccessorAndMutatorFunctionsNotInlined` query - TFunctionsPackageQuery(TTrivialAccessorAndMutatorFunctionsNotInlinedQuery()) + TQueryCPP(TFunctionsPackageQuery(TTrivialAccessorAndMutatorFunctionsNotInlinedQuery())) } Query invalidFunctionReturnTypeQuery() { //autogenerate `Query` type result = // `Query` type for `invalidFunctionReturnType` query - TFunctionsPackageQuery(TInvalidFunctionReturnTypeQuery()) + TQueryCPP(TFunctionsPackageQuery(TInvalidFunctionReturnTypeQuery())) } Query recursiveFunctionsQuery() { //autogenerate `Query` type result = // `Query` type for `recursiveFunctions` query - TFunctionsPackageQuery(TRecursiveFunctionsQuery()) + TQueryCPP(TFunctionsPackageQuery(TRecursiveFunctionsQuery())) } Query functionNoReturnAttributeConditionAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `functionNoReturnAttributeConditionAutosar` query - TFunctionsPackageQuery(TFunctionNoReturnAttributeConditionAutosarQuery()) + TQueryCPP(TFunctionsPackageQuery(TFunctionNoReturnAttributeConditionAutosarQuery())) } Query nonVoidFunctionDoesNotReturnAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `nonVoidFunctionDoesNotReturnAutosar` query - TFunctionsPackageQuery(TNonVoidFunctionDoesNotReturnAutosarQuery()) + TQueryCPP(TFunctionsPackageQuery(TNonVoidFunctionDoesNotReturnAutosarQuery())) } Query functionReturnMultipleValueConditionQuery() { //autogenerate `Query` type result = // `Query` type for `functionReturnMultipleValueCondition` query - TFunctionsPackageQuery(TFunctionReturnMultipleValueConditionQuery()) + TQueryCPP(TFunctionsPackageQuery(TFunctionReturnMultipleValueConditionQuery())) } Query assmemblerInstructionsConditionQuery() { //autogenerate `Query` type result = // `Query` type for `assmemblerInstructionsCondition` query - TFunctionsPackageQuery(TAssmemblerInstructionsConditionQuery()) + TQueryCPP(TFunctionsPackageQuery(TAssmemblerInstructionsConditionQuery())) } Query assemblyLanguageConditionQuery() { //autogenerate `Query` type result = // `Query` type for `assemblyLanguageCondition` query - TFunctionsPackageQuery(TAssemblyLanguageConditionQuery()) + TQueryCPP(TFunctionsPackageQuery(TAssemblyLanguageConditionQuery())) } Query functionReturnAutomaticVarConditionQuery() { //autogenerate `Query` type result = // `Query` type for `functionReturnAutomaticVarCondition` query - TFunctionsPackageQuery(TFunctionReturnAutomaticVarConditionQuery()) + TQueryCPP(TFunctionsPackageQuery(TFunctionReturnAutomaticVarConditionQuery())) } Query functionIdentifierConditionQuery() { //autogenerate `Query` type result = // `Query` type for `functionIdentifierCondition` query - TFunctionsPackageQuery(TFunctionIdentifierConditionQuery()) + TQueryCPP(TFunctionsPackageQuery(TFunctionIdentifierConditionQuery())) } Query functionWithMismatchedLanguageLinkageQuery() { //autogenerate `Query` type result = // `Query` type for `functionWithMismatchedLanguageLinkage` query - TFunctionsPackageQuery(TFunctionWithMismatchedLanguageLinkageQuery()) + TQueryCPP(TFunctionsPackageQuery(TFunctionWithMismatchedLanguageLinkageQuery())) } Query nonVoidFunctionDoesNotReturnCertQuery() { //autogenerate `Query` type result = // `Query` type for `nonVoidFunctionDoesNotReturnCert` query - TFunctionsPackageQuery(TNonVoidFunctionDoesNotReturnCertQuery()) + TQueryCPP(TFunctionsPackageQuery(TNonVoidFunctionDoesNotReturnCertQuery())) } Query functionNoReturnAttributeConditionCertQuery() { //autogenerate `Query` type result = // `Query` type for `functionNoReturnAttributeConditionCert` query - TFunctionsPackageQuery(TFunctionNoReturnAttributeConditionCertQuery()) + TQueryCPP(TFunctionsPackageQuery(TFunctionNoReturnAttributeConditionCertQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/IO.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/IO.qll similarity index 83% rename from cpp/common/src/codingstandards/cpp/exclusions/IO.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/IO.qll index 496d809361..cefa031820 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/IO.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/IO.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype IOQuery = TInterleavedInputOutputWithoutFlushQuery() or @@ -38,20 +39,20 @@ module IOPackage { //autogenerate `Query` type result = // `Query` type for `interleavedInputOutputWithoutFlush` query - TIOPackageQuery(TInterleavedInputOutputWithoutFlushQuery()) + TQueryCPP(TIOPackageQuery(TInterleavedInputOutputWithoutFlushQuery())) } Query interleavedInputOutputWithoutPositionQuery() { //autogenerate `Query` type result = // `Query` type for `interleavedInputOutputWithoutPosition` query - TIOPackageQuery(TInterleavedInputOutputWithoutPositionQuery()) + TQueryCPP(TIOPackageQuery(TInterleavedInputOutputWithoutPositionQuery())) } Query closeFilesWhenTheyAreNoLongerNeededQuery() { //autogenerate `Query` type result = // `Query` type for `closeFilesWhenTheyAreNoLongerNeeded` query - TIOPackageQuery(TCloseFilesWhenTheyAreNoLongerNeededQuery()) + TQueryCPP(TIOPackageQuery(TCloseFilesWhenTheyAreNoLongerNeededQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Includes.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Includes.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/Includes.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Includes.qll index cf75ea337a..f446959ac5 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Includes.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Includes.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype IncludesQuery = TUnusedIncludeDirectivesQuery() or @@ -65,41 +66,41 @@ module IncludesPackage { //autogenerate `Query` type result = // `Query` type for `unusedIncludeDirectives` query - TIncludesPackageQuery(TUnusedIncludeDirectivesQuery()) + TQueryCPP(TIncludesPackageQuery(TUnusedIncludeDirectivesQuery())) } Query violationsOfOneDefinitionRuleQuery() { //autogenerate `Query` type result = // `Query` type for `violationsOfOneDefinitionRule` query - TIncludesPackageQuery(TViolationsOfOneDefinitionRuleQuery()) + TQueryCPP(TIncludesPackageQuery(TViolationsOfOneDefinitionRuleQuery())) } Query headerFileExpectedFileNameExtensionQuery() { //autogenerate `Query` type result = // `Query` type for `headerFileExpectedFileNameExtension` query - TIncludesPackageQuery(THeaderFileExpectedFileNameExtensionQuery()) + TQueryCPP(TIncludesPackageQuery(THeaderFileExpectedFileNameExtensionQuery())) } Query fileNameExtensionCppQuery() { //autogenerate `Query` type result = // `Query` type for `fileNameExtensionCpp` query - TIncludesPackageQuery(TFileNameExtensionCppQuery()) + TQueryCPP(TIncludesPackageQuery(TFileNameExtensionCppQuery())) } Query externalLinkageNotDeclaredInHeaderFileQuery() { //autogenerate `Query` type result = // `Query` type for `externalLinkageNotDeclaredInHeaderFile` query - TIncludesPackageQuery(TExternalLinkageNotDeclaredInHeaderFileQuery()) + TQueryCPP(TIncludesPackageQuery(TExternalLinkageNotDeclaredInHeaderFileQuery())) } Query includeGuardsNotProvidedQuery() { //autogenerate `Query` type result = // `Query` type for `includeGuardsNotProvided` query - TIncludesPackageQuery(TIncludeGuardsNotProvidedQuery()) + TQueryCPP(TIncludesPackageQuery(TIncludeGuardsNotProvidedQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Inheritance.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Inheritance.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Inheritance.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Inheritance.qll index e45a64f9b2..fe8ae3f155 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Inheritance.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Inheritance.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype InheritanceQuery = TPublicInheritanceNotUsedForIsARelationshipQuery() or @@ -128,90 +129,90 @@ module InheritancePackage { //autogenerate `Query` type result = // `Query` type for `publicInheritanceNotUsedForIsARelationship` query - TInheritancePackageQuery(TPublicInheritanceNotUsedForIsARelationshipQuery()) + TQueryCPP(TInheritancePackageQuery(TPublicInheritanceNotUsedForIsARelationshipQuery())) } Query nonPublicInheritanceNotUsedForHasARelationshipQuery() { //autogenerate `Query` type result = // `Query` type for `nonPublicInheritanceNotUsedForHasARelationship` query - TInheritancePackageQuery(TNonPublicInheritanceNotUsedForHasARelationshipQuery()) + TQueryCPP(TInheritancePackageQuery(TNonPublicInheritanceNotUsedForHasARelationshipQuery())) } Query classDerivedFromMoreThanOneNonInterfaceBaseClassQuery() { //autogenerate `Query` type result = // `Query` type for `classDerivedFromMoreThanOneNonInterfaceBaseClass` query - TInheritancePackageQuery(TClassDerivedFromMoreThanOneNonInterfaceBaseClassQuery()) + TQueryCPP(TInheritancePackageQuery(TClassDerivedFromMoreThanOneNonInterfaceBaseClassQuery())) } Query hierarchiesShouldBeBasedOnInterfaceClassesQuery() { //autogenerate `Query` type result = // `Query` type for `hierarchiesShouldBeBasedOnInterfaceClasses` query - TInheritancePackageQuery(THierarchiesShouldBeBasedOnInterfaceClassesQuery()) + TQueryCPP(TInheritancePackageQuery(THierarchiesShouldBeBasedOnInterfaceClassesQuery())) } Query classesShouldNotBeDerivedFromVirtualBasesQuery() { //autogenerate `Query` type result = // `Query` type for `classesShouldNotBeDerivedFromVirtualBases` query - TInheritancePackageQuery(TClassesShouldNotBeDerivedFromVirtualBasesQuery()) + TQueryCPP(TInheritancePackageQuery(TClassesShouldNotBeDerivedFromVirtualBasesQuery())) } Query baseClassCanBeVirtualOnlyInDiamondHierarchyQuery() { //autogenerate `Query` type result = // `Query` type for `baseClassCanBeVirtualOnlyInDiamondHierarchy` query - TInheritancePackageQuery(TBaseClassCanBeVirtualOnlyInDiamondHierarchyQuery()) + TQueryCPP(TInheritancePackageQuery(TBaseClassCanBeVirtualOnlyInDiamondHierarchyQuery())) } Query accessibleBaseClassBothVirtualAndNonVirtualInHierarchyQuery() { //autogenerate `Query` type result = // `Query` type for `accessibleBaseClassBothVirtualAndNonVirtualInHierarchy` query - TInheritancePackageQuery(TAccessibleBaseClassBothVirtualAndNonVirtualInHierarchyQuery()) + TQueryCPP(TInheritancePackageQuery(TAccessibleBaseClassBothVirtualAndNonVirtualInHierarchyQuery())) } Query uniqueAccessibleEntityNamesInMultipleInheritanceQuery() { //autogenerate `Query` type result = // `Query` type for `uniqueAccessibleEntityNamesInMultipleInheritance` query - TInheritancePackageQuery(TUniqueAccessibleEntityNamesInMultipleInheritanceQuery()) + TQueryCPP(TInheritancePackageQuery(TUniqueAccessibleEntityNamesInMultipleInheritanceQuery())) } Query dynamicTypeOfThisUsedFromConstructorOrDestructorQuery() { //autogenerate `Query` type result = // `Query` type for `dynamicTypeOfThisUsedFromConstructorOrDestructor` query - TInheritancePackageQuery(TDynamicTypeOfThisUsedFromConstructorOrDestructorQuery()) + TQueryCPP(TInheritancePackageQuery(TDynamicTypeOfThisUsedFromConstructorOrDestructorQuery())) } Query downcastingShouldNotBePerformedOnPolymorphicTypesQuery() { //autogenerate `Query` type result = // `Query` type for `downcastingShouldNotBePerformedOnPolymorphicTypes` query - TInheritancePackageQuery(TDowncastingShouldNotBePerformedOnPolymorphicTypesQuery()) + TQueryCPP(TInheritancePackageQuery(TDowncastingShouldNotBePerformedOnPolymorphicTypesQuery())) } Query doNotInvokeVirtualFunctionsFromConstructorsOrDestructorsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotInvokeVirtualFunctionsFromConstructorsOrDestructors` query - TInheritancePackageQuery(TDoNotInvokeVirtualFunctionsFromConstructorsOrDestructorsQuery()) + TQueryCPP(TInheritancePackageQuery(TDoNotInvokeVirtualFunctionsFromConstructorsOrDestructorsQuery())) } Query doNotSliceDerivedObjectsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotSliceDerivedObjects` query - TInheritancePackageQuery(TDoNotSliceDerivedObjectsQuery()) + TQueryCPP(TInheritancePackageQuery(TDoNotSliceDerivedObjectsQuery())) } Query doNotDeleteAPolymorphicObjectWithoutAVirtualDestructorQuery() { //autogenerate `Query` type result = // `Query` type for `doNotDeleteAPolymorphicObjectWithoutAVirtualDestructor` query - TInheritancePackageQuery(TDoNotDeleteAPolymorphicObjectWithoutAVirtualDestructorQuery()) + TQueryCPP(TInheritancePackageQuery(TDoNotDeleteAPolymorphicObjectWithoutAVirtualDestructorQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Initialization.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Initialization.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Initialization.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Initialization.qll index 14ab828c9e..45ce339b25 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Initialization.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Initialization.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype InitializationQuery = TExplicitConstructorBaseClassInitializationQuery() or @@ -200,146 +201,146 @@ module InitializationPackage { //autogenerate `Query` type result = // `Query` type for `explicitConstructorBaseClassInitialization` query - TInitializationPackageQuery(TExplicitConstructorBaseClassInitializationQuery()) + TQueryCPP(TInitializationPackageQuery(TExplicitConstructorBaseClassInitializationQuery())) } Query nonStaticMemberMultipleInitQuery() { //autogenerate `Query` type result = // `Query` type for `nonStaticMemberMultipleInit` query - TInitializationPackageQuery(TNonStaticMemberMultipleInitQuery()) + TQueryCPP(TInitializationPackageQuery(TNonStaticMemberMultipleInitQuery())) } Query missedNSDMIOpportunityQuery() { //autogenerate `Query` type result = // `Query` type for `missedNSDMIOpportunity` query - TInitializationPackageQuery(TMissedNSDMIOpportunityQuery()) + TQueryCPP(TInitializationPackageQuery(TMissedNSDMIOpportunityQuery())) } Query constructorWithFundamentalArgMissingExplicitQuery() { //autogenerate `Query` type result = // `Query` type for `constructorWithFundamentalArgMissingExplicit` query - TInitializationPackageQuery(TConstructorWithFundamentalArgMissingExplicitQuery()) + TQueryCPP(TInitializationPackageQuery(TConstructorWithFundamentalArgMissingExplicitQuery())) } Query avoidDuplicationInConstructorsQuery() { //autogenerate `Query` type result = // `Query` type for `avoidDuplicationInConstructors` query - TInitializationPackageQuery(TAvoidDuplicationInConstructorsQuery()) + TQueryCPP(TInitializationPackageQuery(TAvoidDuplicationInConstructorsQuery())) } Query useInheritingConstructorsQuery() { //autogenerate `Query` type result = // `Query` type for `useInheritingConstructors` query - TInitializationPackageQuery(TUseInheritingConstructorsQuery()) + TQueryCPP(TInitializationPackageQuery(TUseInheritingConstructorsQuery())) } Query moveConstructorUsesCopySemanticsQuery() { //autogenerate `Query` type result = // `Query` type for `moveConstructorUsesCopySemantics` query - TInitializationPackageQuery(TMoveConstructorUsesCopySemanticsQuery()) + TQueryCPP(TInitializationPackageQuery(TMoveConstructorUsesCopySemanticsQuery())) } Query randomNumberEnginesDefaultInitializedQuery() { //autogenerate `Query` type result = // `Query` type for `randomNumberEnginesDefaultInitialized` query - TInitializationPackageQuery(TRandomNumberEnginesDefaultInitializedQuery()) + TQueryCPP(TInitializationPackageQuery(TRandomNumberEnginesDefaultInitializedQuery())) } Query staticOrThreadLocalObjectsNonConstantInitQuery() { //autogenerate `Query` type result = // `Query` type for `staticOrThreadLocalObjectsNonConstantInit` query - TInitializationPackageQuery(TStaticOrThreadLocalObjectsNonConstantInitQuery()) + TQueryCPP(TInitializationPackageQuery(TStaticOrThreadLocalObjectsNonConstantInitQuery())) } Query initializationListOutOfOrderQuery() { //autogenerate `Query` type result = // `Query` type for `initializationListOutOfOrder` query - TInitializationPackageQuery(TInitializationListOutOfOrderQuery()) + TQueryCPP(TInitializationPackageQuery(TInitializationListOutOfOrderQuery())) } Query useBracedVariableInitializationQuery() { //autogenerate `Query` type result = // `Query` type for `useBracedVariableInitialization` query - TInitializationPackageQuery(TUseBracedVariableInitializationQuery()) + TQueryCPP(TInitializationPackageQuery(TUseBracedVariableInitializationQuery())) } Query avoidAutoWithBracedInitializationQuery() { //autogenerate `Query` type result = // `Query` type for `avoidAutoWithBracedInitialization` query - TInitializationPackageQuery(TAvoidAutoWithBracedInitializationQuery()) + TQueryCPP(TInitializationPackageQuery(TAvoidAutoWithBracedInitializationQuery())) } Query confusingUseOfInitializerListConstructorsQuery() { //autogenerate `Query` type result = // `Query` type for `confusingUseOfInitializerListConstructors` query - TInitializationPackageQuery(TConfusingUseOfInitializerListConstructorsQuery()) + TQueryCPP(TInitializationPackageQuery(TConfusingUseOfInitializerListConstructorsQuery())) } Query multipleLocalDeclaratorsQuery() { //autogenerate `Query` type result = // `Query` type for `multipleLocalDeclarators` query - TInitializationPackageQuery(TMultipleLocalDeclaratorsQuery()) + TQueryCPP(TInitializationPackageQuery(TMultipleLocalDeclaratorsQuery())) } Query multipleGlobalOrMemberDeclaratorsQuery() { //autogenerate `Query` type result = // `Query` type for `multipleGlobalOrMemberDeclarators` query - TInitializationPackageQuery(TMultipleGlobalOrMemberDeclaratorsQuery()) + TQueryCPP(TInitializationPackageQuery(TMultipleGlobalOrMemberDeclaratorsQuery())) } Query useInitBracesToMatchTypeStructureQuery() { //autogenerate `Query` type result = // `Query` type for `useInitBracesToMatchTypeStructure` query - TInitializationPackageQuery(TUseInitBracesToMatchTypeStructureQuery()) + TQueryCPP(TInitializationPackageQuery(TUseInitBracesToMatchTypeStructureQuery())) } Query missingExplicitInitializersQuery() { //autogenerate `Query` type result = // `Query` type for `missingExplicitInitializers` query - TInitializationPackageQuery(TMissingExplicitInitializersQuery()) + TQueryCPP(TInitializationPackageQuery(TMissingExplicitInitializersQuery())) } Query nestedZeroValueInitializationQuery() { //autogenerate `Query` type result = // `Query` type for `nestedZeroValueInitialization` query - TInitializationPackageQuery(TNestedZeroValueInitializationQuery()) + TQueryCPP(TInitializationPackageQuery(TNestedZeroValueInitializationQuery())) } Query cyclesDuringStaticObjectInitQuery() { //autogenerate `Query` type result = // `Query` type for `cyclesDuringStaticObjectInit` query - TInitializationPackageQuery(TCyclesDuringStaticObjectInitQuery()) + TQueryCPP(TInitializationPackageQuery(TCyclesDuringStaticObjectInitQuery())) } Query badlySeededRandomNumberGeneratorQuery() { //autogenerate `Query` type result = // `Query` type for `badlySeededRandomNumberGenerator` query - TInitializationPackageQuery(TBadlySeededRandomNumberGeneratorQuery()) + TQueryCPP(TInitializationPackageQuery(TBadlySeededRandomNumberGeneratorQuery())) } Query useCanonicalOrderForMemberInitQuery() { //autogenerate `Query` type result = // `Query` type for `useCanonicalOrderForMemberInit` query - TInitializationPackageQuery(TUseCanonicalOrderForMemberInitQuery()) + TQueryCPP(TInitializationPackageQuery(TUseCanonicalOrderForMemberInitQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/IntegerConversion.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/IntegerConversion.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/IntegerConversion.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/IntegerConversion.qll index b71d3902e9..2387f7f4c4 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/IntegerConversion.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/IntegerConversion.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype IntegerConversionQuery = TIntegerExpressionLeadToDataLossQuery() or @@ -101,69 +102,69 @@ module IntegerConversionPackage { //autogenerate `Query` type result = // `Query` type for `integerExpressionLeadToDataLoss` query - TIntegerConversionPackageQuery(TIntegerExpressionLeadToDataLossQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TIntegerExpressionLeadToDataLossQuery())) } Query intMultToLongQuery() { //autogenerate `Query` type result = // `Query` type for `intMultToLong` query - TIntegerConversionPackageQuery(TIntMultToLongQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TIntMultToLongQuery())) } Query implicitChangeOfTheSignednessOfTheUnderlyingTypeQuery() { //autogenerate `Query` type result = // `Query` type for `implicitChangeOfTheSignednessOfTheUnderlyingType` query - TIntegerConversionPackageQuery(TImplicitChangeOfTheSignednessOfTheUnderlyingTypeQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TImplicitChangeOfTheSignednessOfTheUnderlyingTypeQuery())) } Query implicitNonConstFloatingIntegralConversionQuery() { //autogenerate `Query` type result = // `Query` type for `implicitNonConstFloatingIntegralConversion` query - TIntegerConversionPackageQuery(TImplicitNonConstFloatingIntegralConversionQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TImplicitNonConstFloatingIntegralConversionQuery())) } Query implicitConstFloatingIntegralConversionQuery() { //autogenerate `Query` type result = // `Query` type for `implicitConstFloatingIntegralConversion` query - TIntegerConversionPackageQuery(TImplicitConstFloatingIntegralConversionQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TImplicitConstFloatingIntegralConversionQuery())) } Query implicitNonConstConversionToSmallerUnderlyingTypeQuery() { //autogenerate `Query` type result = // `Query` type for `implicitNonConstConversionToSmallerUnderlyingType` query - TIntegerConversionPackageQuery(TImplicitNonConstConversionToSmallerUnderlyingTypeQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TImplicitNonConstConversionToSmallerUnderlyingTypeQuery())) } Query implicitConstConversionToSmallerUnderlyingTypeQuery() { //autogenerate `Query` type result = // `Query` type for `implicitConstConversionToSmallerUnderlyingType` query - TIntegerConversionPackageQuery(TImplicitConstConversionToSmallerUnderlyingTypeQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TImplicitConstConversionToSmallerUnderlyingTypeQuery())) } Query explicitFloatingIntegralConversionOfACValueExprQuery() { //autogenerate `Query` type result = // `Query` type for `explicitFloatingIntegralConversionOfACValueExpr` query - TIntegerConversionPackageQuery(TExplicitFloatingIntegralConversionOfACValueExprQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TExplicitFloatingIntegralConversionOfACValueExprQuery())) } Query explicitWideningConversionOfACValueExprQuery() { //autogenerate `Query` type result = // `Query` type for `explicitWideningConversionOfACValueExpr` query - TIntegerConversionPackageQuery(TExplicitWideningConversionOfACValueExprQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TExplicitWideningConversionOfACValueExprQuery())) } Query explicitSignednessConversionOfCValueQuery() { //autogenerate `Query` type result = // `Query` type for `explicitSignednessConversionOfCValue` query - TIntegerConversionPackageQuery(TExplicitSignednessConversionOfCValueQuery()) + TQueryCPP(TIntegerConversionPackageQuery(TExplicitSignednessConversionOfCValueQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Invariants.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Invariants.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/Invariants.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Invariants.qll index c9b07bce25..a084dfcdf8 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Invariants.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Invariants.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype InvariantsQuery = TMemoryManagementFunctionInvariantsQuery() or @@ -65,41 +66,41 @@ module InvariantsPackage { //autogenerate `Query` type result = // `Query` type for `memoryManagementFunctionInvariants` query - TInvariantsPackageQuery(TMemoryManagementFunctionInvariantsQuery()) + TQueryCPP(TInvariantsPackageQuery(TMemoryManagementFunctionInvariantsQuery())) } Query orderingPredicatesInvariantsQuery() { //autogenerate `Query` type result = // `Query` type for `orderingPredicatesInvariants` query - TInvariantsPackageQuery(TOrderingPredicatesInvariantsQuery()) + TQueryCPP(TInvariantsPackageQuery(TOrderingPredicatesInvariantsQuery())) } Query provideAValidOrderingPredicateQuery() { //autogenerate `Query` type result = // `Query` type for `provideAValidOrderingPredicate` query - TInvariantsPackageQuery(TProvideAValidOrderingPredicateQuery()) + TQueryCPP(TInvariantsPackageQuery(TProvideAValidOrderingPredicateQuery())) } Query signalHandlerMustBeAPlainOldFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `signalHandlerMustBeAPlainOldFunction` query - TInvariantsPackageQuery(TSignalHandlerMustBeAPlainOldFunctionQuery()) + TQueryCPP(TInvariantsPackageQuery(TSignalHandlerMustBeAPlainOldFunctionQuery())) } Query honorTerminationReplacementHandlerRequirementsQuery() { //autogenerate `Query` type result = // `Query` type for `honorTerminationReplacementHandlerRequirements` query - TInvariantsPackageQuery(THonorTerminationReplacementHandlerRequirementsQuery()) + TQueryCPP(TInvariantsPackageQuery(THonorTerminationReplacementHandlerRequirementsQuery())) } Query honorNewReplacementHandlerRequirementsQuery() { //autogenerate `Query` type result = // `Query` type for `honorNewReplacementHandlerRequirements` query - TInvariantsPackageQuery(THonorNewReplacementHandlerRequirementsQuery()) + TQueryCPP(TInvariantsPackageQuery(THonorNewReplacementHandlerRequirementsQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Iterators.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Iterators.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/Iterators.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Iterators.qll index 4a34df84ec..619e955fd4 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Iterators.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Iterators.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype IteratorsQuery = TIteratorImplicitlyConvertedToConstIteratorQuery() or @@ -74,48 +75,48 @@ module IteratorsPackage { //autogenerate `Query` type result = // `Query` type for `iteratorImplicitlyConvertedToConstIterator` query - TIteratorsPackageQuery(TIteratorImplicitlyConvertedToConstIteratorQuery()) + TQueryCPP(TIteratorsPackageQuery(TIteratorImplicitlyConvertedToConstIteratorQuery())) } Query validContainerElementAccessQuery() { //autogenerate `Query` type result = // `Query` type for `validContainerElementAccess` query - TIteratorsPackageQuery(TValidContainerElementAccessQuery()) + TQueryCPP(TIteratorsPackageQuery(TValidContainerElementAccessQuery())) } Query usesValidContainerElementAccessQuery() { //autogenerate `Query` type result = // `Query` type for `usesValidContainerElementAccess` query - TIteratorsPackageQuery(TUsesValidContainerElementAccessQuery()) + TQueryCPP(TIteratorsPackageQuery(TUsesValidContainerElementAccessQuery())) } Query useValidIteratorRangesQuery() { //autogenerate `Query` type result = // `Query` type for `useValidIteratorRanges` query - TIteratorsPackageQuery(TUseValidIteratorRangesQuery()) + TQueryCPP(TIteratorsPackageQuery(TUseValidIteratorRangesQuery())) } Query doNotSubtractIteratorsForDifferentContainersQuery() { //autogenerate `Query` type result = // `Query` type for `doNotSubtractIteratorsForDifferentContainers` query - TIteratorsPackageQuery(TDoNotSubtractIteratorsForDifferentContainersQuery()) + TQueryCPP(TIteratorsPackageQuery(TDoNotSubtractIteratorsForDifferentContainersQuery())) } Query doNotUseAnAdditiveOperatorOnAnIteratorQuery() { //autogenerate `Query` type result = // `Query` type for `doNotUseAnAdditiveOperatorOnAnIterator` query - TIteratorsPackageQuery(TDoNotUseAnAdditiveOperatorOnAnIteratorQuery()) + TQueryCPP(TIteratorsPackageQuery(TDoNotUseAnAdditiveOperatorOnAnIteratorQuery())) } Query useValidReferencesForElementsOfStringQuery() { //autogenerate `Query` type result = // `Query` type for `useValidReferencesForElementsOfString` query - TIteratorsPackageQuery(TUseValidReferencesForElementsOfStringQuery()) + TQueryCPP(TIteratorsPackageQuery(TUseValidReferencesForElementsOfStringQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Lambdas.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Lambdas.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Lambdas.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Lambdas.qll index 8f85e00aec..7d51a5022d 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Lambdas.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Lambdas.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype LambdasQuery = TImplicitLambdaCaptureQuery() or @@ -110,76 +111,76 @@ module LambdasPackage { //autogenerate `Query` type result = // `Query` type for `implicitLambdaCapture` query - TLambdasPackageQuery(TImplicitLambdaCaptureQuery()) + TQueryCPP(TLambdasPackageQuery(TImplicitLambdaCaptureQuery())) } Query lambdaExpressionWithoutParameterListQuery() { //autogenerate `Query` type result = // `Query` type for `lambdaExpressionWithoutParameterList` query - TLambdasPackageQuery(TLambdaExpressionWithoutParameterListQuery()) + TQueryCPP(TLambdasPackageQuery(TLambdaExpressionWithoutParameterListQuery())) } Query returnedLambdaObjectOutlivesCaptureByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `returnedLambdaObjectOutlivesCaptureByReference` query - TLambdasPackageQuery(TReturnedLambdaObjectOutlivesCaptureByReferenceQuery()) + TQueryCPP(TLambdasPackageQuery(TReturnedLambdaObjectOutlivesCaptureByReferenceQuery())) } Query movedLambdaObjectOutlivesCaptureByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `movedLambdaObjectOutlivesCaptureByReference` query - TLambdasPackageQuery(TMovedLambdaObjectOutlivesCaptureByReferenceQuery()) + TQueryCPP(TLambdasPackageQuery(TMovedLambdaObjectOutlivesCaptureByReferenceQuery())) } Query lambdaWithImplicitNonVoidReturnTypeQuery() { //autogenerate `Query` type result = // `Query` type for `lambdaWithImplicitNonVoidReturnType` query - TLambdasPackageQuery(TLambdaWithImplicitNonVoidReturnTypeQuery()) + TQueryCPP(TLambdasPackageQuery(TLambdaWithImplicitNonVoidReturnTypeQuery())) } Query lambdaPassedToDecltypeQuery() { //autogenerate `Query` type result = // `Query` type for `lambdaPassedToDecltype` query - TLambdasPackageQuery(TLambdaPassedToDecltypeQuery()) + TQueryCPP(TLambdasPackageQuery(TLambdaPassedToDecltypeQuery())) } Query lambdaPassedToTypeidQuery() { //autogenerate `Query` type result = // `Query` type for `lambdaPassedToTypeid` query - TLambdasPackageQuery(TLambdaPassedToTypeidQuery()) + TQueryCPP(TLambdasPackageQuery(TLambdaPassedToTypeidQuery())) } Query lambdaExpressionInLambdaExpressionQuery() { //autogenerate `Query` type result = // `Query` type for `lambdaExpressionInLambdaExpression` query - TLambdasPackageQuery(TLambdaExpressionInLambdaExpressionQuery()) + TQueryCPP(TLambdasPackageQuery(TLambdaExpressionInLambdaExpressionQuery())) } Query identicalLambdaExpressionsQuery() { //autogenerate `Query` type result = // `Query` type for `identicalLambdaExpressions` query - TLambdasPackageQuery(TIdenticalLambdaExpressionsQuery()) + TQueryCPP(TLambdasPackageQuery(TIdenticalLambdaExpressionsQuery())) } Query returningLambdaObjectWithCaptureByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `returningLambdaObjectWithCaptureByReference` query - TLambdasPackageQuery(TReturningLambdaObjectWithCaptureByReferenceQuery()) + TQueryCPP(TLambdasPackageQuery(TReturningLambdaObjectWithCaptureByReferenceQuery())) } Query escapingLambdaObjectWithCaptureByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `escapingLambdaObjectWithCaptureByReference` query - TLambdasPackageQuery(TEscapingLambdaObjectWithCaptureByReferenceQuery()) + TQueryCPP(TLambdasPackageQuery(TEscapingLambdaObjectWithCaptureByReferenceQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Literals.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Literals.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Literals.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Literals.qll index 949e9a50c4..1413b0a6fc 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Literals.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Literals.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype LiteralsQuery = TUseCorrectIntervalForDigitSequencesSeparatorsQuery() or @@ -110,76 +111,76 @@ module LiteralsPackage { //autogenerate `Query` type result = // `Query` type for `useCorrectIntervalForDigitSequencesSeparators` query - TLiteralsPackageQuery(TUseCorrectIntervalForDigitSequencesSeparatorsQuery()) + TQueryCPP(TLiteralsPackageQuery(TUseCorrectIntervalForDigitSequencesSeparatorsQuery())) } Query escapeSequenceOutsideISOQuery() { //autogenerate `Query` type result = // `Query` type for `escapeSequenceOutsideISO` query - TLiteralsPackageQuery(TEscapeSequenceOutsideISOQuery()) + TQueryCPP(TLiteralsPackageQuery(TEscapeSequenceOutsideISOQuery())) } Query hexadecimalConstantsShouldBeUpperCaseQuery() { //autogenerate `Query` type result = // `Query` type for `hexadecimalConstantsShouldBeUpperCase` query - TLiteralsPackageQuery(THexadecimalConstantsShouldBeUpperCaseQuery()) + TQueryCPP(TLiteralsPackageQuery(THexadecimalConstantsShouldBeUpperCaseQuery())) } Query nullPointerConstantNotNullptrQuery() { //autogenerate `Query` type result = // `Query` type for `nullPointerConstantNotNullptr` query - TLiteralsPackageQuery(TNullPointerConstantNotNullptrQuery()) + TQueryCPP(TLiteralsPackageQuery(TNullPointerConstantNotNullptrQuery())) } Query literalValueUsedOutsideTypeInitQuery() { //autogenerate `Query` type result = // `Query` type for `literalValueUsedOutsideTypeInit` query - TLiteralsPackageQuery(TLiteralValueUsedOutsideTypeInitQuery()) + TQueryCPP(TLiteralsPackageQuery(TLiteralValueUsedOutsideTypeInitQuery())) } Query useOfNonZeroOctalLiteralQuery() { //autogenerate `Query` type result = // `Query` type for `useOfNonZeroOctalLiteral` query - TLiteralsPackageQuery(TUseOfNonZeroOctalLiteralQuery()) + TQueryCPP(TLiteralsPackageQuery(TUseOfNonZeroOctalLiteralQuery())) } Query useOfNonZeroOctalEscapeQuery() { //autogenerate `Query` type result = // `Query` type for `useOfNonZeroOctalEscape` query - TLiteralsPackageQuery(TUseOfNonZeroOctalEscapeQuery()) + TQueryCPP(TLiteralsPackageQuery(TUseOfNonZeroOctalEscapeQuery())) } Query missingUSuffixQuery() { //autogenerate `Query` type result = // `Query` type for `missingUSuffix` query - TLiteralsPackageQuery(TMissingUSuffixQuery()) + TQueryCPP(TLiteralsPackageQuery(TMissingUSuffixQuery())) } Query literalSuffixNotUpperCaseQuery() { //autogenerate `Query` type result = // `Query` type for `literalSuffixNotUpperCase` query - TLiteralsPackageQuery(TLiteralSuffixNotUpperCaseQuery()) + TQueryCPP(TLiteralsPackageQuery(TLiteralSuffixNotUpperCaseQuery())) } Query nullUsedAsIntegerValueQuery() { //autogenerate `Query` type result = // `Query` type for `nullUsedAsIntegerValue` query - TLiteralsPackageQuery(TNullUsedAsIntegerValueQuery()) + TQueryCPP(TLiteralsPackageQuery(TNullUsedAsIntegerValueQuery())) } Query literalZeroUsedAsNullPointerConstantQuery() { //autogenerate `Query` type result = // `Query` type for `literalZeroUsedAsNullPointerConstant` query - TLiteralsPackageQuery(TLiteralZeroUsedAsNullPointerConstantQuery()) + TQueryCPP(TLiteralsPackageQuery(TLiteralZeroUsedAsNullPointerConstantQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Loops.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Loops.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Loops.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Loops.qll index 9f6705c9ff..65286eed6f 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Loops.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Loops.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype LoopsQuery = TUnusedLoopCounterForContainerIterationQuery() or @@ -128,90 +129,90 @@ module LoopsPackage { //autogenerate `Query` type result = // `Query` type for `unusedLoopCounterForContainerIteration` query - TLoopsPackageQuery(TUnusedLoopCounterForContainerIterationQuery()) + TQueryCPP(TLoopsPackageQuery(TUnusedLoopCounterForContainerIterationQuery())) } Query multipleLoopCountersQuery() { //autogenerate `Query` type result = // `Query` type for `multipleLoopCounters` query - TLoopsPackageQuery(TMultipleLoopCountersQuery()) + TQueryCPP(TLoopsPackageQuery(TMultipleLoopCountersQuery())) } Query floatingPointLoopCounterQuery() { //autogenerate `Query` type result = // `Query` type for `floatingPointLoopCounter` query - TLoopsPackageQuery(TFloatingPointLoopCounterQuery()) + TQueryCPP(TLoopsPackageQuery(TFloatingPointLoopCounterQuery())) } Query doStatementsShouldNotBeUsedQuery() { //autogenerate `Query` type result = // `Query` type for `doStatementsShouldNotBeUsed` query - TLoopsPackageQuery(TDoStatementsShouldNotBeUsedQuery()) + TQueryCPP(TLoopsPackageQuery(TDoStatementsShouldNotBeUsedQuery())) } Query forLoopInitializesNonLoopCounterQuery() { //autogenerate `Query` type result = // `Query` type for `forLoopInitializesNonLoopCounter` query - TLoopsPackageQuery(TForLoopInitializesNonLoopCounterQuery()) + TQueryCPP(TLoopsPackageQuery(TForLoopInitializesNonLoopCounterQuery())) } Query forLoopModifiesNonLoopCounterQuery() { //autogenerate `Query` type result = // `Query` type for `forLoopModifiesNonLoopCounter` query - TLoopsPackageQuery(TForLoopModifiesNonLoopCounterQuery()) + TQueryCPP(TLoopsPackageQuery(TForLoopModifiesNonLoopCounterQuery())) } Query notEqualsInLoopConditionQuery() { //autogenerate `Query` type result = // `Query` type for `notEqualsInLoopCondition` query - TLoopsPackageQuery(TNotEqualsInLoopConditionQuery()) + TQueryCPP(TLoopsPackageQuery(TNotEqualsInLoopConditionQuery())) } Query loopCounterModifiedWithinConditionQuery() { //autogenerate `Query` type result = // `Query` type for `loopCounterModifiedWithinCondition` query - TLoopsPackageQuery(TLoopCounterModifiedWithinConditionQuery()) + TQueryCPP(TLoopsPackageQuery(TLoopCounterModifiedWithinConditionQuery())) } Query loopCounterModifiedWithinStatementQuery() { //autogenerate `Query` type result = // `Query` type for `loopCounterModifiedWithinStatement` query - TLoopsPackageQuery(TLoopCounterModifiedWithinStatementQuery()) + TQueryCPP(TLoopsPackageQuery(TLoopCounterModifiedWithinStatementQuery())) } Query irregularLoopCounterModificationQuery() { //autogenerate `Query` type result = // `Query` type for `irregularLoopCounterModification` query - TLoopsPackageQuery(TIrregularLoopCounterModificationQuery()) + TQueryCPP(TLoopsPackageQuery(TIrregularLoopCounterModificationQuery())) } Query loopControlVariableModifiedInLoopConditionQuery() { //autogenerate `Query` type result = // `Query` type for `loopControlVariableModifiedInLoopCondition` query - TLoopsPackageQuery(TLoopControlVariableModifiedInLoopConditionQuery()) + TQueryCPP(TLoopsPackageQuery(TLoopControlVariableModifiedInLoopConditionQuery())) } Query loopControlVariableModifiedInLoopExpressionQuery() { //autogenerate `Query` type result = // `Query` type for `loopControlVariableModifiedInLoopExpression` query - TLoopsPackageQuery(TLoopControlVariableModifiedInLoopExpressionQuery()) + TQueryCPP(TLoopsPackageQuery(TLoopControlVariableModifiedInLoopExpressionQuery())) } Query nonBooleanLoopControlVariableQuery() { //autogenerate `Query` type result = // `Query` type for `nonBooleanLoopControlVariable` query - TLoopsPackageQuery(TNonBooleanLoopControlVariableQuery()) + TQueryCPP(TLoopsPackageQuery(TNonBooleanLoopControlVariableQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Macros.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Macros.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Macros.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Macros.qll index cc7c1b8a09..e9055e8083 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Macros.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Macros.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype MacrosQuery = TPreProcessorShallOnlyBeUsedForCertainDirectivesPatternsQuery() or @@ -119,83 +120,83 @@ module MacrosPackage { //autogenerate `Query` type result = // `Query` type for `preProcessorShallOnlyBeUsedForCertainDirectivesPatterns` query - TMacrosPackageQuery(TPreProcessorShallOnlyBeUsedForCertainDirectivesPatternsQuery()) + TQueryCPP(TMacrosPackageQuery(TPreProcessorShallOnlyBeUsedForCertainDirectivesPatternsQuery())) } Query charactersOccurInHeaderFileNameOrInIncludeDirectiveQuery() { //autogenerate `Query` type result = // `Query` type for `charactersOccurInHeaderFileNameOrInIncludeDirective` query - TMacrosPackageQuery(TCharactersOccurInHeaderFileNameOrInIncludeDirectiveQuery()) + TQueryCPP(TMacrosPackageQuery(TCharactersOccurInHeaderFileNameOrInIncludeDirectiveQuery())) } Query errorDirectiveUsedQuery() { //autogenerate `Query` type result = // `Query` type for `errorDirectiveUsed` query - TMacrosPackageQuery(TErrorDirectiveUsedQuery()) + TQueryCPP(TMacrosPackageQuery(TErrorDirectiveUsedQuery())) } Query pragmaDirectiveUsedQuery() { //autogenerate `Query` type result = // `Query` type for `pragmaDirectiveUsed` query - TMacrosPackageQuery(TPragmaDirectiveUsedQuery()) + TQueryCPP(TMacrosPackageQuery(TPragmaDirectiveUsedQuery())) } Query includeDirectivesNotPrecededByDirectivesOrCommentsQuery() { //autogenerate `Query` type result = // `Query` type for `includeDirectivesNotPrecededByDirectivesOrComments` query - TMacrosPackageQuery(TIncludeDirectivesNotPrecededByDirectivesOrCommentsQuery()) + TQueryCPP(TMacrosPackageQuery(TIncludeDirectivesNotPrecededByDirectivesOrCommentsQuery())) } Query macrosShallOnlyBeDefinedOrUndefdInTheGlobalNamespaceQuery() { //autogenerate `Query` type result = // `Query` type for `macrosShallOnlyBeDefinedOrUndefdInTheGlobalNamespace` query - TMacrosPackageQuery(TMacrosShallOnlyBeDefinedOrUndefdInTheGlobalNamespaceQuery()) + TQueryCPP(TMacrosPackageQuery(TMacrosShallOnlyBeDefinedOrUndefdInTheGlobalNamespaceQuery())) } Query functionLikeMacroArgsContainHashTokenQuery() { //autogenerate `Query` type result = // `Query` type for `functionLikeMacroArgsContainHashToken` query - TMacrosPackageQuery(TFunctionLikeMacroArgsContainHashTokenQuery()) + TQueryCPP(TMacrosPackageQuery(TFunctionLikeMacroArgsContainHashTokenQuery())) } Query functionLikeMacroParameterNotEnclosedInParenthesesQuery() { //autogenerate `Query` type result = // `Query` type for `functionLikeMacroParameterNotEnclosedInParentheses` query - TMacrosPackageQuery(TFunctionLikeMacroParameterNotEnclosedInParenthesesQuery()) + TQueryCPP(TMacrosPackageQuery(TFunctionLikeMacroParameterNotEnclosedInParenthesesQuery())) } Query undefinedMacroIdentifiersUsedInQuery() { //autogenerate `Query` type result = // `Query` type for `undefinedMacroIdentifiersUsedIn` query - TMacrosPackageQuery(TUndefinedMacroIdentifiersUsedInQuery()) + TQueryCPP(TMacrosPackageQuery(TUndefinedMacroIdentifiersUsedInQuery())) } Query definedPreProcessorOperatorInOneOfTheTwoStandardFormsQuery() { //autogenerate `Query` type result = // `Query` type for `definedPreProcessorOperatorInOneOfTheTwoStandardForms` query - TMacrosPackageQuery(TDefinedPreProcessorOperatorInOneOfTheTwoStandardFormsQuery()) + TQueryCPP(TMacrosPackageQuery(TDefinedPreProcessorOperatorInOneOfTheTwoStandardFormsQuery())) } Query moreThanOneOccurrenceHashOperatorInMacroDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `moreThanOneOccurrenceHashOperatorInMacroDefinition` query - TMacrosPackageQuery(TMoreThanOneOccurrenceHashOperatorInMacroDefinitionQuery()) + TQueryCPP(TMacrosPackageQuery(TMoreThanOneOccurrenceHashOperatorInMacroDefinitionQuery())) } Query hashOperatorsShouldNotBeUsedQuery() { //autogenerate `Query` type result = // `Query` type for `hashOperatorsShouldNotBeUsed` query - TMacrosPackageQuery(THashOperatorsShouldNotBeUsedQuery()) + TQueryCPP(TMacrosPackageQuery(THashOperatorsShouldNotBeUsedQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/MoveForward.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/MoveForward.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/MoveForward.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/MoveForward.qll index ea26f01fda..c79931bf58 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/MoveForward.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/MoveForward.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype MoveForwardQuery = TMovedFromObjectReadAccessedQuery() or @@ -74,48 +75,48 @@ module MoveForwardPackage { //autogenerate `Query` type result = // `Query` type for `movedFromObjectReadAccessed` query - TMoveForwardPackageQuery(TMovedFromObjectReadAccessedQuery()) + TQueryCPP(TMoveForwardPackageQuery(TMovedFromObjectReadAccessedQuery())) } Query forwardingValuesToOtherFunctionsQuery() { //autogenerate `Query` type result = // `Query` type for `forwardingValuesToOtherFunctions` query - TMoveForwardPackageQuery(TForwardingValuesToOtherFunctionsQuery()) + TQueryCPP(TMoveForwardPackageQuery(TForwardingValuesToOtherFunctionsQuery())) } Query moveUsedOnConstObjectsQuery() { //autogenerate `Query` type result = // `Query` type for `moveUsedOnConstObjects` query - TMoveForwardPackageQuery(TMoveUsedOnConstObjectsQuery()) + TQueryCPP(TMoveForwardPackageQuery(TMoveUsedOnConstObjectsQuery())) } Query argumentToForwardSubsequentlyUsedQuery() { //autogenerate `Query` type result = // `Query` type for `argumentToForwardSubsequentlyUsed` query - TMoveForwardPackageQuery(TArgumentToForwardSubsequentlyUsedQuery()) + TQueryCPP(TMoveForwardPackageQuery(TArgumentToForwardSubsequentlyUsedQuery())) } Query moveFromConsumeParametersRvalRefQuery() { //autogenerate `Query` type result = // `Query` type for `moveFromConsumeParametersRvalRef` query - TMoveForwardPackageQuery(TMoveFromConsumeParametersRvalRefQuery()) + TQueryCPP(TMoveForwardPackageQuery(TMoveFromConsumeParametersRvalRefQuery())) } Query forwardForwardingReferencesQuery() { //autogenerate `Query` type result = // `Query` type for `forwardForwardingReferences` query - TMoveForwardPackageQuery(TForwardForwardingReferencesQuery()) + TQueryCPP(TMoveForwardPackageQuery(TForwardForwardingReferencesQuery())) } Query doNotRelyOnTheValueOfAMovedFromObjectQuery() { //autogenerate `Query` type result = // `Query` type for `doNotRelyOnTheValueOfAMovedFromObject` query - TMoveForwardPackageQuery(TDoNotRelyOnTheValueOfAMovedFromObjectQuery()) + TQueryCPP(TMoveForwardPackageQuery(TDoNotRelyOnTheValueOfAMovedFromObjectQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Naming.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Naming.qll similarity index 86% rename from cpp/common/src/codingstandards/cpp/exclusions/Naming.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Naming.qll index 958ccd9594..5ab4fc7647 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Naming.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Naming.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype NamingQuery = TUserDefinedLiteralOperatorSuffixViolationQuery() or @@ -254,188 +255,188 @@ module NamingPackage { //autogenerate `Query` type result = // `Query` type for `userDefinedLiteralOperatorSuffixViolation` query - TNamingPackageQuery(TUserDefinedLiteralOperatorSuffixViolationQuery()) + TQueryCPP(TNamingPackageQuery(TUserDefinedLiteralOperatorSuffixViolationQuery())) } Query identifierHidingQuery() { //autogenerate `Query` type result = // `Query` type for `identifierHiding` query - TNamingPackageQuery(TIdentifierHidingQuery()) + TQueryCPP(TNamingPackageQuery(TIdentifierHidingQuery())) } Query identifierNameOfStaticNonMemberObjectReusedInNamespaceQuery() { //autogenerate `Query` type result = // `Query` type for `identifierNameOfStaticNonMemberObjectReusedInNamespace` query - TNamingPackageQuery(TIdentifierNameOfStaticNonMemberObjectReusedInNamespaceQuery()) + TQueryCPP(TNamingPackageQuery(TIdentifierNameOfStaticNonMemberObjectReusedInNamespaceQuery())) } Query identifierNameOfStaticFunctionReusedInNamespaceQuery() { //autogenerate `Query` type result = // `Query` type for `identifierNameOfStaticFunctionReusedInNamespace` query - TNamingPackageQuery(TIdentifierNameOfStaticFunctionReusedInNamespaceQuery()) + TQueryCPP(TNamingPackageQuery(TIdentifierNameOfStaticFunctionReusedInNamespaceQuery())) } Query identifierNameOfAStaticFunctionIsReusedQuery() { //autogenerate `Query` type result = // `Query` type for `identifierNameOfAStaticFunctionIsReused` query - TNamingPackageQuery(TIdentifierNameOfAStaticFunctionIsReusedQuery()) + TQueryCPP(TNamingPackageQuery(TIdentifierNameOfAStaticFunctionIsReusedQuery())) } Query identifierNameOfANonMemberObjectWithExternalOrInternalLinkageIsReusedQuery() { //autogenerate `Query` type result = // `Query` type for `identifierNameOfANonMemberObjectWithExternalOrInternalLinkageIsReused` query - TNamingPackageQuery(TIdentifierNameOfANonMemberObjectWithExternalOrInternalLinkageIsReusedQuery()) + TQueryCPP(TNamingPackageQuery(TIdentifierNameOfANonMemberObjectWithExternalOrInternalLinkageIsReusedQuery())) } Query classOrEnumerationNameHiddenByAVariableInTheSameScopeQuery() { //autogenerate `Query` type result = // `Query` type for `classOrEnumerationNameHiddenByAVariableInTheSameScope` query - TNamingPackageQuery(TClassOrEnumerationNameHiddenByAVariableInTheSameScopeQuery()) + TQueryCPP(TNamingPackageQuery(TClassOrEnumerationNameHiddenByAVariableInTheSameScopeQuery())) } Query classOrEnumerationNameHiddenByAFunctionInTheSameScopeQuery() { //autogenerate `Query` type result = // `Query` type for `classOrEnumerationNameHiddenByAFunctionInTheSameScope` query - TNamingPackageQuery(TClassOrEnumerationNameHiddenByAFunctionInTheSameScopeQuery()) + TQueryCPP(TNamingPackageQuery(TClassOrEnumerationNameHiddenByAFunctionInTheSameScopeQuery())) } Query classOrEnumerationNameHiddenByAnEnumeratorInTheSameScopeQuery() { //autogenerate `Query` type result = // `Query` type for `classOrEnumerationNameHiddenByAnEnumeratorInTheSameScope` query - TNamingPackageQuery(TClassOrEnumerationNameHiddenByAnEnumeratorInTheSameScopeQuery()) + TQueryCPP(TNamingPackageQuery(TClassOrEnumerationNameHiddenByAnEnumeratorInTheSameScopeQuery())) } Query universalCharacterNamesUsedOutsideCharacterOrStringLiteralsQuery() { //autogenerate `Query` type result = // `Query` type for `universalCharacterNamesUsedOutsideCharacterOrStringLiterals` query - TNamingPackageQuery(TUniversalCharacterNamesUsedOutsideCharacterOrStringLiteralsQuery()) + TQueryCPP(TNamingPackageQuery(TUniversalCharacterNamesUsedOutsideCharacterOrStringLiteralsQuery())) } Query characterOutsideTheLanguageStandardBasicSourceCharacterSetUsedInTheSourceCodeQuery() { //autogenerate `Query` type result = // `Query` type for `characterOutsideTheLanguageStandardBasicSourceCharacterSetUsedInTheSourceCode` query - TNamingPackageQuery(TCharacterOutsideTheLanguageStandardBasicSourceCharacterSetUsedInTheSourceCodeQuery()) + TQueryCPP(TNamingPackageQuery(TCharacterOutsideTheLanguageStandardBasicSourceCharacterSetUsedInTheSourceCodeQuery())) } Query invalidCharacterInStringLiteralQuery() { //autogenerate `Query` type result = // `Query` type for `invalidCharacterInStringLiteral` query - TNamingPackageQuery(TInvalidCharacterInStringLiteralQuery()) + TQueryCPP(TNamingPackageQuery(TInvalidCharacterInStringLiteralQuery())) } Query invalidCharacterInCommentQuery() { //autogenerate `Query` type result = // `Query` type for `invalidCharacterInComment` query - TNamingPackageQuery(TInvalidCharacterInCommentQuery()) + TQueryCPP(TNamingPackageQuery(TInvalidCharacterInCommentQuery())) } Query nameOfStandardLibraryMacroOrObjectReusedQuery() { //autogenerate `Query` type result = // `Query` type for `nameOfStandardLibraryMacroOrObjectReused` query - TNamingPackageQuery(TNameOfStandardLibraryMacroOrObjectReusedQuery()) + TQueryCPP(TNamingPackageQuery(TNameOfStandardLibraryMacroOrObjectReusedQuery())) } Query nameOfStandardLibraryFunctionIsOverriddenQuery() { //autogenerate `Query` type result = // `Query` type for `nameOfStandardLibraryFunctionIsOverridden` query - TNamingPackageQuery(TNameOfStandardLibraryFunctionIsOverriddenQuery()) + TQueryCPP(TNamingPackageQuery(TNameOfStandardLibraryFunctionIsOverriddenQuery())) } Query differentIdentifiersNotTypographicallyUnambiguousQuery() { //autogenerate `Query` type result = // `Query` type for `differentIdentifiersNotTypographicallyUnambiguous` query - TNamingPackageQuery(TDifferentIdentifiersNotTypographicallyUnambiguousQuery()) + TQueryCPP(TNamingPackageQuery(TDifferentIdentifiersNotTypographicallyUnambiguousQuery())) } Query identifierMainUsedForAFunctionOtherThanTheGlobalFunctionMainQuery() { //autogenerate `Query` type result = // `Query` type for `identifierMainUsedForAFunctionOtherThanTheGlobalFunctionMain` query - TNamingPackageQuery(TIdentifierMainUsedForAFunctionOtherThanTheGlobalFunctionMainQuery()) + TQueryCPP(TNamingPackageQuery(TIdentifierMainUsedForAFunctionOtherThanTheGlobalFunctionMainQuery())) } Query unnamedNamespacesInHeaderFileQuery() { //autogenerate `Query` type result = // `Query` type for `unnamedNamespacesInHeaderFile` query - TNamingPackageQuery(TUnnamedNamespacesInHeaderFileQuery()) + TQueryCPP(TNamingPackageQuery(TUnnamedNamespacesInHeaderFileQuery())) } Query nonIdenticalIdentifierUsedForTheParameterInReDeclarationOfAFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `nonIdenticalIdentifierUsedForTheParameterInReDeclarationOfAFunction` query - TNamingPackageQuery(TNonIdenticalIdentifierUsedForTheParameterInReDeclarationOfAFunctionQuery()) + TQueryCPP(TNamingPackageQuery(TNonIdenticalIdentifierUsedForTheParameterInReDeclarationOfAFunctionQuery())) } Query redefiningOfStandardLibraryNameQuery() { //autogenerate `Query` type result = // `Query` type for `redefiningOfStandardLibraryName` query - TNamingPackageQuery(TRedefiningOfStandardLibraryNameQuery()) + TQueryCPP(TNamingPackageQuery(TRedefiningOfStandardLibraryNameQuery())) } Query reuseOfReservedIdentifierQuery() { //autogenerate `Query` type result = // `Query` type for `reuseOfReservedIdentifier` query - TNamingPackageQuery(TReuseOfReservedIdentifierQuery()) + TQueryCPP(TNamingPackageQuery(TReuseOfReservedIdentifierQuery())) } Query useOfSingleUnderscoreReservedPrefixQuery() { //autogenerate `Query` type result = // `Query` type for `useOfSingleUnderscoreReservedPrefix` query - TNamingPackageQuery(TUseOfSingleUnderscoreReservedPrefixQuery()) + TQueryCPP(TNamingPackageQuery(TUseOfSingleUnderscoreReservedPrefixQuery())) } Query useOfDoubleUnderscoreReservedPrefixQuery() { //autogenerate `Query` type result = // `Query` type for `useOfDoubleUnderscoreReservedPrefix` query - TNamingPackageQuery(TUseOfDoubleUnderscoreReservedPrefixQuery()) + TQueryCPP(TNamingPackageQuery(TUseOfDoubleUnderscoreReservedPrefixQuery())) } Query useOfReservedLiteralSuffixIdentifierQuery() { //autogenerate `Query` type result = // `Query` type for `useOfReservedLiteralSuffixIdentifier` query - TNamingPackageQuery(TUseOfReservedLiteralSuffixIdentifierQuery()) + TQueryCPP(TNamingPackageQuery(TUseOfReservedLiteralSuffixIdentifierQuery())) } Query objectReusesReservedNameQuery() { //autogenerate `Query` type result = // `Query` type for `objectReusesReservedName` query - TNamingPackageQuery(TObjectReusesReservedNameQuery()) + TQueryCPP(TNamingPackageQuery(TObjectReusesReservedNameQuery())) } Query functionReusesReservedNameQuery() { //autogenerate `Query` type result = // `Query` type for `functionReusesReservedName` query - TNamingPackageQuery(TFunctionReusesReservedNameQuery()) + TQueryCPP(TNamingPackageQuery(TFunctionReusesReservedNameQuery())) } Query enumeratorReusesReservedNameQuery() { //autogenerate `Query` type result = // `Query` type for `enumeratorReusesReservedName` query - TNamingPackageQuery(TEnumeratorReusesReservedNameQuery()) + TQueryCPP(TNamingPackageQuery(TEnumeratorReusesReservedNameQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Null.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Null.qll similarity index 83% rename from cpp/common/src/codingstandards/cpp/exclusions/Null.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Null.qll index 3b3a6412a0..c0befae569 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Null.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Null.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype NullQuery = TNullPointersDereferencedQuery() or @@ -38,20 +39,20 @@ module NullPackage { //autogenerate `Query` type result = // `Query` type for `nullPointersDereferenced` query - TNullPackageQuery(TNullPointersDereferencedQuery()) + TQueryCPP(TNullPackageQuery(TNullPointersDereferencedQuery())) } Query parameterNotPassedByReferenceQuery() { //autogenerate `Query` type result = // `Query` type for `parameterNotPassedByReference` query - TNullPackageQuery(TParameterNotPassedByReferenceQuery()) + TQueryCPP(TNullPackageQuery(TParameterNotPassedByReferenceQuery())) } Query doNotAttemptToCreateAStringFromANullPointerQuery() { //autogenerate `Query` type result = // `Query` type for `doNotAttemptToCreateAStringFromANullPointer` query - TNullPackageQuery(TDoNotAttemptToCreateAStringFromANullPointerQuery()) + TQueryCPP(TNullPackageQuery(TDoNotAttemptToCreateAStringFromANullPointerQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/OperatorInvariants.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/OperatorInvariants.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/OperatorInvariants.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/OperatorInvariants.qll index 3ab31245b0..51026ef8b4 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/OperatorInvariants.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/OperatorInvariants.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype OperatorInvariantsQuery = TUserDefinedCopyAndMoveUseNoThrowSwapFunctionQuery() or @@ -92,62 +93,62 @@ module OperatorInvariantsPackage { //autogenerate `Query` type result = // `Query` type for `userDefinedCopyAndMoveUseNoThrowSwapFunction` query - TOperatorInvariantsPackageQuery(TUserDefinedCopyAndMoveUseNoThrowSwapFunctionQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TUserDefinedCopyAndMoveUseNoThrowSwapFunctionQuery())) } Query copyAssignmentAndAMoveHandleSelfAssignmentQuery() { //autogenerate `Query` type result = // `Query` type for `copyAssignmentAndAMoveHandleSelfAssignment` query - TOperatorInvariantsPackageQuery(TCopyAssignmentAndAMoveHandleSelfAssignmentQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TCopyAssignmentAndAMoveHandleSelfAssignmentQuery())) } Query assignmentOperatorReturnThisQuery() { //autogenerate `Query` type result = // `Query` type for `assignmentOperatorReturnThis` query - TOperatorInvariantsPackageQuery(TAssignmentOperatorReturnThisQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TAssignmentOperatorReturnThisQuery())) } Query binaryOperatorAndBitwiseOperatorReturnAPrvalueQuery() { //autogenerate `Query` type result = // `Query` type for `binaryOperatorAndBitwiseOperatorReturnAPrvalue` query - TOperatorInvariantsPackageQuery(TBinaryOperatorAndBitwiseOperatorReturnAPrvalueQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TBinaryOperatorAndBitwiseOperatorReturnAPrvalueQuery())) } Query oppositeOperatorsNotDefinedInTermsOfOtherQuery() { //autogenerate `Query` type result = // `Query` type for `oppositeOperatorsNotDefinedInTermsOfOther` query - TOperatorInvariantsPackageQuery(TOppositeOperatorsNotDefinedInTermsOfOtherQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TOppositeOperatorsNotDefinedInTermsOfOtherQuery())) } Query hashSpecializationsHaveANoexceptFunctionCallOperatorQuery() { //autogenerate `Query` type result = // `Query` type for `hashSpecializationsHaveANoexceptFunctionCallOperator` query - TOperatorInvariantsPackageQuery(THashSpecializationsHaveANoexceptFunctionCallOperatorQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(THashSpecializationsHaveANoexceptFunctionCallOperatorQuery())) } Query semanticEquivalenceBetweenOperatorFormNotPreservedQuery() { //autogenerate `Query` type result = // `Query` type for `semanticEquivalenceBetweenOperatorFormNotPreserved` query - TOperatorInvariantsPackageQuery(TSemanticEquivalenceBetweenOperatorFormNotPreservedQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TSemanticEquivalenceBetweenOperatorFormNotPreservedQuery())) } Query gracefullyHandleSelfCopyAssignmentQuery() { //autogenerate `Query` type result = // `Query` type for `gracefullyHandleSelfCopyAssignment` query - TOperatorInvariantsPackageQuery(TGracefullyHandleSelfCopyAssignmentQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TGracefullyHandleSelfCopyAssignmentQuery())) } Query copyOperationsMustNotMutateTheSourceObjectQuery() { //autogenerate `Query` type result = // `Query` type for `copyOperationsMustNotMutateTheSourceObject` query - TOperatorInvariantsPackageQuery(TCopyOperationsMustNotMutateTheSourceObjectQuery()) + TQueryCPP(TOperatorInvariantsPackageQuery(TCopyOperationsMustNotMutateTheSourceObjectQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Operators.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Operators.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Operators.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Operators.qll index 56ac0c6f00..d395d6fd5a 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Operators.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Operators.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype OperatorsQuery = TUserDefinedAssignmentOperatorVirtualQuery() or @@ -146,104 +147,104 @@ module OperatorsPackage { //autogenerate `Query` type result = // `Query` type for `userDefinedAssignmentOperatorVirtual` query - TOperatorsPackageQuery(TUserDefinedAssignmentOperatorVirtualQuery()) + TQueryCPP(TOperatorsPackageQuery(TUserDefinedAssignmentOperatorVirtualQuery())) } Query copyAndMoveNotDeclaredProtectedQuery() { //autogenerate `Query` type result = // `Query` type for `copyAndMoveNotDeclaredProtected` query - TOperatorsPackageQuery(TCopyAndMoveNotDeclaredProtectedQuery()) + TQueryCPP(TOperatorsPackageQuery(TCopyAndMoveNotDeclaredProtectedQuery())) } Query operatorsShouldBeDeclaredWithTheRefQualifierQuery() { //autogenerate `Query` type result = // `Query` type for `operatorsShouldBeDeclaredWithTheRefQualifier` query - TOperatorsPackageQuery(TOperatorsShouldBeDeclaredWithTheRefQualifierQuery()) + TQueryCPP(TOperatorsPackageQuery(TOperatorsShouldBeDeclaredWithTheRefQualifierQuery())) } Query relationalOperatorShallReturnABooleanValueQuery() { //autogenerate `Query` type result = // `Query` type for `relationalOperatorShallReturnABooleanValue` query - TOperatorsPackageQuery(TRelationalOperatorShallReturnABooleanValueQuery()) + TQueryCPP(TOperatorsPackageQuery(TRelationalOperatorShallReturnABooleanValueQuery())) } Query functionThatContainsForwardingReferenceAsItsArgumentOverloadedQuery() { //autogenerate `Query` type result = // `Query` type for `functionThatContainsForwardingReferenceAsItsArgumentOverloaded` query - TOperatorsPackageQuery(TFunctionThatContainsForwardingReferenceAsItsArgumentOverloadedQuery()) + TQueryCPP(TOperatorsPackageQuery(TFunctionThatContainsForwardingReferenceAsItsArgumentOverloadedQuery())) } Query missingConstOperatorSubscriptQuery() { //autogenerate `Query` type result = // `Query` type for `missingConstOperatorSubscript` query - TOperatorsPackageQuery(TMissingConstOperatorSubscriptQuery()) + TQueryCPP(TOperatorsPackageQuery(TMissingConstOperatorSubscriptQuery())) } Query userDefinedConversionOperatorsNotDefinedExplicitQuery() { //autogenerate `Query` type result = // `Query` type for `userDefinedConversionOperatorsNotDefinedExplicit` query - TOperatorsPackageQuery(TUserDefinedConversionOperatorsNotDefinedExplicitQuery()) + TQueryCPP(TOperatorsPackageQuery(TUserDefinedConversionOperatorsNotDefinedExplicitQuery())) } Query userDefinedConversionOperatorsShouldNotBeUsedQuery() { //autogenerate `Query` type result = // `Query` type for `userDefinedConversionOperatorsShouldNotBeUsed` query - TOperatorsPackageQuery(TUserDefinedConversionOperatorsShouldNotBeUsedQuery()) + TQueryCPP(TOperatorsPackageQuery(TUserDefinedConversionOperatorsShouldNotBeUsedQuery())) } Query comparisonOperatorsNotNonMemberFunctionsWithIdenticalParameterTypesAndNoexceptQuery() { //autogenerate `Query` type result = // `Query` type for `comparisonOperatorsNotNonMemberFunctionsWithIdenticalParameterTypesAndNoexcept` query - TOperatorsPackageQuery(TComparisonOperatorsNotNonMemberFunctionsWithIdenticalParameterTypesAndNoexceptQuery()) + TQueryCPP(TOperatorsPackageQuery(TComparisonOperatorsNotNonMemberFunctionsWithIdenticalParameterTypesAndNoexceptQuery())) } Query nonMemberGenericOperatorConditionQuery() { //autogenerate `Query` type result = // `Query` type for `nonMemberGenericOperatorCondition` query - TOperatorsPackageQuery(TNonMemberGenericOperatorConditionQuery()) + TQueryCPP(TOperatorsPackageQuery(TNonMemberGenericOperatorConditionQuery())) } Query unsignedBitwiseOperatorWithoutCastQuery() { //autogenerate `Query` type result = // `Query` type for `unsignedBitwiseOperatorWithoutCast` query - TOperatorsPackageQuery(TUnsignedBitwiseOperatorWithoutCastQuery()) + TQueryCPP(TOperatorsPackageQuery(TUnsignedBitwiseOperatorWithoutCastQuery())) } Query commaOperatorAndOperatorAndTheOperatorOverloadedQuery() { //autogenerate `Query` type result = // `Query` type for `commaOperatorAndOperatorAndTheOperatorOverloaded` query - TOperatorsPackageQuery(TCommaOperatorAndOperatorAndTheOperatorOverloadedQuery()) + TQueryCPP(TOperatorsPackageQuery(TCommaOperatorAndOperatorAndTheOperatorOverloadedQuery())) } Query eachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBoolQuery() { //autogenerate `Query` type result = // `Query` type for `eachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool` query - TOperatorsPackageQuery(TEachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBoolQuery()) + TQueryCPP(TOperatorsPackageQuery(TEachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBoolQuery())) } Query unaryMinusOperatorAppliedToAnExpressionWhoseUnderlyingTypeIsUnsignedQuery() { //autogenerate `Query` type result = // `Query` type for `unaryMinusOperatorAppliedToAnExpressionWhoseUnderlyingTypeIsUnsigned` query - TOperatorsPackageQuery(TUnaryMinusOperatorAppliedToAnExpressionWhoseUnderlyingTypeIsUnsignedQuery()) + TQueryCPP(TOperatorsPackageQuery(TUnaryMinusOperatorAppliedToAnExpressionWhoseUnderlyingTypeIsUnsignedQuery())) } Query unaryOperatorOverloadedQuery() { //autogenerate `Query` type result = // `Query` type for `unaryOperatorOverloaded` query - TOperatorsPackageQuery(TUnaryOperatorOverloadedQuery()) + TQueryCPP(TOperatorsPackageQuery(TUnaryOperatorOverloadedQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/OrderOfEvaluation.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/OrderOfEvaluation.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/OrderOfEvaluation.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/OrderOfEvaluation.qll index fc3a90e3af..2ac5b428da 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/OrderOfEvaluation.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/OrderOfEvaluation.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype OrderOfEvaluationQuery = TExpressionShouldNotRelyOnOrderOfEvaluationQuery() or @@ -65,41 +66,41 @@ module OrderOfEvaluationPackage { //autogenerate `Query` type result = // `Query` type for `expressionShouldNotRelyOnOrderOfEvaluation` query - TOrderOfEvaluationPackageQuery(TExpressionShouldNotRelyOnOrderOfEvaluationQuery()) + TQueryCPP(TOrderOfEvaluationPackageQuery(TExpressionShouldNotRelyOnOrderOfEvaluationQuery())) } Query operandsOfALogicalAndOrNotParenthesizedQuery() { //autogenerate `Query` type result = // `Query` type for `operandsOfALogicalAndOrNotParenthesized` query - TOrderOfEvaluationPackageQuery(TOperandsOfALogicalAndOrNotParenthesizedQuery()) + TQueryCPP(TOrderOfEvaluationPackageQuery(TOperandsOfALogicalAndOrNotParenthesizedQuery())) } Query explicitConstructionOfUnnamedTemporaryQuery() { //autogenerate `Query` type result = // `Query` type for `explicitConstructionOfUnnamedTemporary` query - TOrderOfEvaluationPackageQuery(TExplicitConstructionOfUnnamedTemporaryQuery()) + TQueryCPP(TOrderOfEvaluationPackageQuery(TExplicitConstructionOfUnnamedTemporaryQuery())) } Query gratuitousUseOfParenthesesQuery() { //autogenerate `Query` type result = // `Query` type for `gratuitousUseOfParentheses` query - TOrderOfEvaluationPackageQuery(TGratuitousUseOfParenthesesQuery()) + TQueryCPP(TOrderOfEvaluationPackageQuery(TGratuitousUseOfParenthesesQuery())) } Query incrementAndDecrementOperatorsMixedWithOtherOperatorsInExpressionQuery() { //autogenerate `Query` type result = // `Query` type for `incrementAndDecrementOperatorsMixedWithOtherOperatorsInExpression` query - TOrderOfEvaluationPackageQuery(TIncrementAndDecrementOperatorsMixedWithOtherOperatorsInExpressionQuery()) + TQueryCPP(TOrderOfEvaluationPackageQuery(TIncrementAndDecrementOperatorsMixedWithOtherOperatorsInExpressionQuery())) } Query assignmentInSubExpressionQuery() { //autogenerate `Query` type result = // `Query` type for `assignmentInSubExpression` query - TOrderOfEvaluationPackageQuery(TAssignmentInSubExpressionQuery()) + TQueryCPP(TOrderOfEvaluationPackageQuery(TAssignmentInSubExpressionQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/OutOfBounds.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/OutOfBounds.qll similarity index 83% rename from cpp/common/src/codingstandards/cpp/exclusions/OutOfBounds.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/OutOfBounds.qll index 8dbfea59c8..c85fa998e1 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/OutOfBounds.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/OutOfBounds.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype OutOfBoundsQuery = TContainerAccessWithoutRangeCheckAutosarQuery() or @@ -47,27 +48,27 @@ module OutOfBoundsPackage { //autogenerate `Query` type result = // `Query` type for `containerAccessWithoutRangeCheckAutosar` query - TOutOfBoundsPackageQuery(TContainerAccessWithoutRangeCheckAutosarQuery()) + TQueryCPP(TOutOfBoundsPackageQuery(TContainerAccessWithoutRangeCheckAutosarQuery())) } Query containerAccessWithoutRangeCheckCertQuery() { //autogenerate `Query` type result = // `Query` type for `containerAccessWithoutRangeCheckCert` query - TOutOfBoundsPackageQuery(TContainerAccessWithoutRangeCheckCertQuery()) + TQueryCPP(TOutOfBoundsPackageQuery(TContainerAccessWithoutRangeCheckCertQuery())) } Query guaranteeGenericCppLibraryFunctionsDoNotOverflowQuery() { //autogenerate `Query` type result = // `Query` type for `guaranteeGenericCppLibraryFunctionsDoNotOverflow` query - TOutOfBoundsPackageQuery(TGuaranteeGenericCppLibraryFunctionsDoNotOverflowQuery()) + TQueryCPP(TOutOfBoundsPackageQuery(TGuaranteeGenericCppLibraryFunctionsDoNotOverflowQuery())) } Query rangeCheckStringElementAccessQuery() { //autogenerate `Query` type result = // `Query` type for `rangeCheckStringElementAccess` query - TOutOfBoundsPackageQuery(TRangeCheckStringElementAccessQuery()) + TQueryCPP(TOutOfBoundsPackageQuery(TRangeCheckStringElementAccessQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Pointers.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Pointers.qll similarity index 86% rename from cpp/common/src/codingstandards/cpp/exclusions/Pointers.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Pointers.qll index 4ab33b9a46..07e68a5a9c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Pointers.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Pointers.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype PointersQuery = TPointerToAnElementOfAnArrayPassedToASmartPointerQuery() or @@ -218,160 +219,160 @@ module PointersPackage { //autogenerate `Query` type result = // `Query` type for `pointerToAnElementOfAnArrayPassedToASmartPointer` query - TPointersPackageQuery(TPointerToAnElementOfAnArrayPassedToASmartPointerQuery()) + TQueryCPP(TPointersPackageQuery(TPointerToAnElementOfAnArrayPassedToASmartPointerQuery())) } Query declarationContainLessThanTwoLevelsOfIndirectionQuery() { //autogenerate `Query` type result = // `Query` type for `declarationContainLessThanTwoLevelsOfIndirection` query - TPointersPackageQuery(TDeclarationContainLessThanTwoLevelsOfIndirectionQuery()) + TQueryCPP(TPointersPackageQuery(TDeclarationContainLessThanTwoLevelsOfIndirectionQuery())) } Query pointerArithmeticUsedWithPointersToNonFinalClassesQuery() { //autogenerate `Query` type result = // `Query` type for `pointerArithmeticUsedWithPointersToNonFinalClasses` query - TPointersPackageQuery(TPointerArithmeticUsedWithPointersToNonFinalClassesQuery()) + TQueryCPP(TPointersPackageQuery(TPointerArithmeticUsedWithPointersToNonFinalClassesQuery())) } Query pointerToMemberVirtualFunctionWithNullPointerConstantQuery() { //autogenerate `Query` type result = // `Query` type for `pointerToMemberVirtualFunctionWithNullPointerConstant` query - TPointersPackageQuery(TPointerToMemberVirtualFunctionWithNullPointerConstantQuery()) + TQueryCPP(TPointersPackageQuery(TPointerToMemberVirtualFunctionWithNullPointerConstantQuery())) } Query deletingPointerToIncompleteTypeQuery() { //autogenerate `Query` type result = // `Query` type for `deletingPointerToIncompleteType` query - TPointersPackageQuery(TDeletingPointerToIncompleteTypeQuery()) + TQueryCPP(TPointersPackageQuery(TDeletingPointerToIncompleteTypeQuery())) } Query pointerToMemberAccessNonExistentClassMembersQuery() { //autogenerate `Query` type result = // `Query` type for `pointerToMemberAccessNonExistentClassMembers` query - TPointersPackageQuery(TPointerToMemberAccessNonExistentClassMembersQuery()) + TQueryCPP(TPointersPackageQuery(TPointerToMemberAccessNonExistentClassMembersQuery())) } Query nullPointerToMemberAccessNonExistentClassMembersQuery() { //autogenerate `Query` type result = // `Query` type for `nullPointerToMemberAccessNonExistentClassMembers` query - TPointersPackageQuery(TNullPointerToMemberAccessNonExistentClassMembersQuery()) + TQueryCPP(TPointersPackageQuery(TNullPointerToMemberAccessNonExistentClassMembersQuery())) } Query uninitializedStaticPointerToMemberUseQuery() { //autogenerate `Query` type result = // `Query` type for `uninitializedStaticPointerToMemberUse` query - TPointersPackageQuery(TUninitializedStaticPointerToMemberUseQuery()) + TQueryCPP(TPointersPackageQuery(TUninitializedStaticPointerToMemberUseQuery())) } Query indexingNotTheOnlyFormOfPointerArithmeticQuery() { //autogenerate `Query` type result = // `Query` type for `indexingNotTheOnlyFormOfPointerArithmetic` query - TPointersPackageQuery(TIndexingNotTheOnlyFormOfPointerArithmeticQuery()) + TQueryCPP(TPointersPackageQuery(TIndexingNotTheOnlyFormOfPointerArithmeticQuery())) } Query pointerAndDerivedPointerAccessDifferentArrayQuery() { //autogenerate `Query` type result = // `Query` type for `pointerAndDerivedPointerAccessDifferentArray` query - TPointersPackageQuery(TPointerAndDerivedPointerAccessDifferentArrayQuery()) + TQueryCPP(TPointersPackageQuery(TPointerAndDerivedPointerAccessDifferentArrayQuery())) } Query pointerSubtractionOnDifferentArraysQuery() { //autogenerate `Query` type result = // `Query` type for `pointerSubtractionOnDifferentArrays` query - TPointersPackageQuery(TPointerSubtractionOnDifferentArraysQuery()) + TQueryCPP(TPointersPackageQuery(TPointerSubtractionOnDifferentArraysQuery())) } Query appliedToObjectsOfPointerTypeQuery() { //autogenerate `Query` type result = // `Query` type for `appliedToObjectsOfPointerType` query - TPointersPackageQuery(TAppliedToObjectsOfPointerTypeQuery()) + TQueryCPP(TPointersPackageQuery(TAppliedToObjectsOfPointerTypeQuery())) } Query identifierWithArrayTypePassedAsFunctionArgumentDecayToAPointerQuery() { //autogenerate `Query` type result = // `Query` type for `identifierWithArrayTypePassedAsFunctionArgumentDecayToAPointer` query - TPointersPackageQuery(TIdentifierWithArrayTypePassedAsFunctionArgumentDecayToAPointerQuery()) + TQueryCPP(TPointersPackageQuery(TIdentifierWithArrayTypePassedAsFunctionArgumentDecayToAPointerQuery())) } Query pointerToAVirtualBaseClassCastToAPointerQuery() { //autogenerate `Query` type result = // `Query` type for `pointerToAVirtualBaseClassCastToAPointer` query - TPointersPackageQuery(TPointerToAVirtualBaseClassCastToAPointerQuery()) + TQueryCPP(TPointersPackageQuery(TPointerToAVirtualBaseClassCastToAPointerQuery())) } Query castNotConvertPointerToFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `castNotConvertPointerToFunction` query - TPointersPackageQuery(TCastNotConvertPointerToFunctionQuery()) + TQueryCPP(TPointersPackageQuery(TCastNotConvertPointerToFunctionQuery())) } Query integerOrPointerToVoidConvertedToPointerTypeQuery() { //autogenerate `Query` type result = // `Query` type for `integerOrPointerToVoidConvertedToPointerType` query - TPointersPackageQuery(TIntegerOrPointerToVoidConvertedToPointerTypeQuery()) + TQueryCPP(TPointersPackageQuery(TIntegerOrPointerToVoidConvertedToPointerTypeQuery())) } Query castConvertAPointerTypeToAnIntegralTypeQuery() { //autogenerate `Query` type result = // `Query` type for `castConvertAPointerTypeToAnIntegralType` query - TPointersPackageQuery(TCastConvertAPointerTypeToAnIntegralTypeQuery()) + TQueryCPP(TPointersPackageQuery(TCastConvertAPointerTypeToAnIntegralTypeQuery())) } Query doNotUsePointerArithmeticOnPolymorphicObjectsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotUsePointerArithmeticOnPolymorphicObjects` query - TPointersPackageQuery(TDoNotUsePointerArithmeticOnPolymorphicObjectsQuery()) + TQueryCPP(TPointersPackageQuery(TDoNotUsePointerArithmeticOnPolymorphicObjectsQuery())) } Query deletingPointerToIncompleteClassQuery() { //autogenerate `Query` type result = // `Query` type for `deletingPointerToIncompleteClass` query - TPointersPackageQuery(TDeletingPointerToIncompleteClassQuery()) + TQueryCPP(TPointersPackageQuery(TDeletingPointerToIncompleteClassQuery())) } Query castOfPointerToIncompleteClassQuery() { //autogenerate `Query` type result = // `Query` type for `castOfPointerToIncompleteClass` query - TPointersPackageQuery(TCastOfPointerToIncompleteClassQuery()) + TQueryCPP(TPointersPackageQuery(TCastOfPointerToIncompleteClassQuery())) } Query useOfPointerToMemberToAccessUndefinedMemberQuery() { //autogenerate `Query` type result = // `Query` type for `useOfPointerToMemberToAccessUndefinedMember` query - TPointersPackageQuery(TUseOfPointerToMemberToAccessUndefinedMemberQuery()) + TQueryCPP(TPointersPackageQuery(TUseOfPointerToMemberToAccessUndefinedMemberQuery())) } Query memberAccessWithUninitializedStaticPointerToMemberQuery() { //autogenerate `Query` type result = // `Query` type for `memberAccessWithUninitializedStaticPointerToMember` query - TPointersPackageQuery(TMemberAccessWithUninitializedStaticPointerToMemberQuery()) + TQueryCPP(TPointersPackageQuery(TMemberAccessWithUninitializedStaticPointerToMemberQuery())) } Query useOfPointerToMemberToAccessNonexistentMemberQuery() { //autogenerate `Query` type result = // `Query` type for `useOfPointerToMemberToAccessNonexistentMember` query - TPointersPackageQuery(TUseOfPointerToMemberToAccessNonexistentMemberQuery()) + TQueryCPP(TPointersPackageQuery(TUseOfPointerToMemberToAccessNonexistentMemberQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Representation.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Representation.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Representation.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Representation.qll index 79bbc41615..d9f2850f95 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Representation.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Representation.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype RepresentationQuery = TBitFieldsShallBeUsedOnlyWhenInterfacingToHardwareOrConformingToCommunicationProtocolsQuery() or @@ -83,55 +84,55 @@ module RepresentationPackage { //autogenerate `Query` type result = // `Query` type for `bitFieldsShallBeUsedOnlyWhenInterfacingToHardwareOrConformingToCommunicationProtocols` query - TRepresentationPackageQuery(TBitFieldsShallBeUsedOnlyWhenInterfacingToHardwareOrConformingToCommunicationProtocolsQuery()) + TQueryCPP(TRepresentationPackageQuery(TBitFieldsShallBeUsedOnlyWhenInterfacingToHardwareOrConformingToCommunicationProtocolsQuery())) } Query auditPossibleHardwareInterfaceDueToBitFieldUsageInDataTypeDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `auditPossibleHardwareInterfaceDueToBitFieldUsageInDataTypeDefinition` query - TRepresentationPackageQuery(TAuditPossibleHardwareInterfaceDueToBitFieldUsageInDataTypeDefinitionQuery()) + TQueryCPP(TRepresentationPackageQuery(TAuditPossibleHardwareInterfaceDueToBitFieldUsageInDataTypeDefinitionQuery())) } Query objectAssignedToAnOverlappingObjectQuery() { //autogenerate `Query` type result = // `Query` type for `objectAssignedToAnOverlappingObject` query - TRepresentationPackageQuery(TObjectAssignedToAnOverlappingObjectQuery()) + TQueryCPP(TRepresentationPackageQuery(TObjectAssignedToAnOverlappingObjectQuery())) } Query underlyingBitRepresentationsOfFloatingPointValuesUsedQuery() { //autogenerate `Query` type result = // `Query` type for `underlyingBitRepresentationsOfFloatingPointValuesUsed` query - TRepresentationPackageQuery(TUnderlyingBitRepresentationsOfFloatingPointValuesUsedQuery()) + TQueryCPP(TRepresentationPackageQuery(TUnderlyingBitRepresentationsOfFloatingPointValuesUsedQuery())) } Query namedBitFieldsWithSignedIntegerTypeShallHaveALengthOfMoreThanOneBitQuery() { //autogenerate `Query` type result = // `Query` type for `namedBitFieldsWithSignedIntegerTypeShallHaveALengthOfMoreThanOneBit` query - TRepresentationPackageQuery(TNamedBitFieldsWithSignedIntegerTypeShallHaveALengthOfMoreThanOneBitQuery()) + TQueryCPP(TRepresentationPackageQuery(TNamedBitFieldsWithSignedIntegerTypeShallHaveALengthOfMoreThanOneBitQuery())) } Query memsetUsedToAccessObjectRepresentationQuery() { //autogenerate `Query` type result = // `Query` type for `memsetUsedToAccessObjectRepresentation` query - TRepresentationPackageQuery(TMemsetUsedToAccessObjectRepresentationQuery()) + TQueryCPP(TRepresentationPackageQuery(TMemsetUsedToAccessObjectRepresentationQuery())) } Query memcmpUsedToAccessObjectRepresentationQuery() { //autogenerate `Query` type result = // `Query` type for `memcmpUsedToAccessObjectRepresentation` query - TRepresentationPackageQuery(TMemcmpUsedToAccessObjectRepresentationQuery()) + TQueryCPP(TRepresentationPackageQuery(TMemcmpUsedToAccessObjectRepresentationQuery())) } Query memcpyUsedToAccessObjectRepresentationQuery() { //autogenerate `Query` type result = // `Query` type for `memcpyUsedToAccessObjectRepresentation` query - TRepresentationPackageQuery(TMemcpyUsedToAccessObjectRepresentationQuery()) + TQueryCPP(TRepresentationPackageQuery(TMemcpyUsedToAccessObjectRepresentationQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll new file mode 100644 index 0000000000..89c804c4ca --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/RuleMetadata.qll @@ -0,0 +1,161 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import cpp +import codingstandards.cpp.exclusions.RuleMetadata +//** Import packages for this language **/ +import Allocations +import BannedFunctions +import BannedLibraries +import BannedSyntax +import BannedTypes +import Classes +import Comments +import Concurrency +import Conditionals +import Const +import DeadCode +import Declarations +import ExceptionSafety +import Exceptions1 +import Exceptions2 +import Expressions +import Freed +import Functions +import IO +import Includes +import Inheritance +import Initialization +import IntegerConversion +import Invariants +import Iterators +import Lambdas +import Literals +import Loops +import Macros +import MoveForward +import Naming +import Null +import OperatorInvariants +import Operators +import OrderOfEvaluation +import OutOfBounds +import Pointers +import Representation +import Scope +import SideEffects1 +import SideEffects2 +import SmartPointers1 +import SmartPointers2 +import Strings +import Templates +import Toolchain +import TrustBoundaries +import TypeRanges +import Uninitialized +import VirtualFunctions + +/** The TQuery type representing this language * */ +newtype TCPPQuery = + TAllocationsPackageQuery(AllocationsQuery q) or + TBannedFunctionsPackageQuery(BannedFunctionsQuery q) or + TBannedLibrariesPackageQuery(BannedLibrariesQuery q) or + TBannedSyntaxPackageQuery(BannedSyntaxQuery q) or + TBannedTypesPackageQuery(BannedTypesQuery q) or + TClassesPackageQuery(ClassesQuery q) or + TCommentsPackageQuery(CommentsQuery q) or + TConcurrencyPackageQuery(ConcurrencyQuery q) or + TConditionalsPackageQuery(ConditionalsQuery q) or + TConstPackageQuery(ConstQuery q) or + TDeadCodePackageQuery(DeadCodeQuery q) or + TDeclarationsPackageQuery(DeclarationsQuery q) or + TExceptionSafetyPackageQuery(ExceptionSafetyQuery q) or + TExceptions1PackageQuery(Exceptions1Query q) or + TExceptions2PackageQuery(Exceptions2Query q) or + TExpressionsPackageQuery(ExpressionsQuery q) or + TFreedPackageQuery(FreedQuery q) or + TFunctionsPackageQuery(FunctionsQuery q) or + TIOPackageQuery(IOQuery q) or + TIncludesPackageQuery(IncludesQuery q) or + TInheritancePackageQuery(InheritanceQuery q) or + TInitializationPackageQuery(InitializationQuery q) or + TIntegerConversionPackageQuery(IntegerConversionQuery q) or + TInvariantsPackageQuery(InvariantsQuery q) or + TIteratorsPackageQuery(IteratorsQuery q) or + TLambdasPackageQuery(LambdasQuery q) or + TLiteralsPackageQuery(LiteralsQuery q) or + TLoopsPackageQuery(LoopsQuery q) or + TMacrosPackageQuery(MacrosQuery q) or + TMoveForwardPackageQuery(MoveForwardQuery q) or + TNamingPackageQuery(NamingQuery q) or + TNullPackageQuery(NullQuery q) or + TOperatorInvariantsPackageQuery(OperatorInvariantsQuery q) or + TOperatorsPackageQuery(OperatorsQuery q) or + TOrderOfEvaluationPackageQuery(OrderOfEvaluationQuery q) or + TOutOfBoundsPackageQuery(OutOfBoundsQuery q) or + TPointersPackageQuery(PointersQuery q) or + TRepresentationPackageQuery(RepresentationQuery q) or + TScopePackageQuery(ScopeQuery q) or + TSideEffects1PackageQuery(SideEffects1Query q) or + TSideEffects2PackageQuery(SideEffects2Query q) or + TSmartPointers1PackageQuery(SmartPointers1Query q) or + TSmartPointers2PackageQuery(SmartPointers2Query q) or + TStringsPackageQuery(StringsQuery q) or + TTemplatesPackageQuery(TemplatesQuery q) or + TToolchainPackageQuery(ToolchainQuery q) or + TTrustBoundariesPackageQuery(TrustBoundariesQuery q) or + TTypeRangesPackageQuery(TypeRangesQuery q) or + TUninitializedPackageQuery(UninitializedQuery q) or + TVirtualFunctionsPackageQuery(VirtualFunctionsQuery q) + +/** The metadata predicate * */ +predicate isQueryMetadata(Query query, string queryId, string ruleId) { + isAllocationsQueryMetadata(query, queryId, ruleId) or + isBannedFunctionsQueryMetadata(query, queryId, ruleId) or + isBannedLibrariesQueryMetadata(query, queryId, ruleId) or + isBannedSyntaxQueryMetadata(query, queryId, ruleId) or + isBannedTypesQueryMetadata(query, queryId, ruleId) or + isClassesQueryMetadata(query, queryId, ruleId) or + isCommentsQueryMetadata(query, queryId, ruleId) or + isConcurrencyQueryMetadata(query, queryId, ruleId) or + isConditionalsQueryMetadata(query, queryId, ruleId) or + isConstQueryMetadata(query, queryId, ruleId) or + isDeadCodeQueryMetadata(query, queryId, ruleId) or + isDeclarationsQueryMetadata(query, queryId, ruleId) or + isExceptionSafetyQueryMetadata(query, queryId, ruleId) or + isExceptions1QueryMetadata(query, queryId, ruleId) or + isExceptions2QueryMetadata(query, queryId, ruleId) or + isExpressionsQueryMetadata(query, queryId, ruleId) or + isFreedQueryMetadata(query, queryId, ruleId) or + isFunctionsQueryMetadata(query, queryId, ruleId) or + isIOQueryMetadata(query, queryId, ruleId) or + isIncludesQueryMetadata(query, queryId, ruleId) or + isInheritanceQueryMetadata(query, queryId, ruleId) or + isInitializationQueryMetadata(query, queryId, ruleId) or + isIntegerConversionQueryMetadata(query, queryId, ruleId) or + isInvariantsQueryMetadata(query, queryId, ruleId) or + isIteratorsQueryMetadata(query, queryId, ruleId) or + isLambdasQueryMetadata(query, queryId, ruleId) or + isLiteralsQueryMetadata(query, queryId, ruleId) or + isLoopsQueryMetadata(query, queryId, ruleId) or + isMacrosQueryMetadata(query, queryId, ruleId) or + isMoveForwardQueryMetadata(query, queryId, ruleId) or + isNamingQueryMetadata(query, queryId, ruleId) or + isNullQueryMetadata(query, queryId, ruleId) or + isOperatorInvariantsQueryMetadata(query, queryId, ruleId) or + isOperatorsQueryMetadata(query, queryId, ruleId) or + isOrderOfEvaluationQueryMetadata(query, queryId, ruleId) or + isOutOfBoundsQueryMetadata(query, queryId, ruleId) or + isPointersQueryMetadata(query, queryId, ruleId) or + isRepresentationQueryMetadata(query, queryId, ruleId) or + isScopeQueryMetadata(query, queryId, ruleId) or + isSideEffects1QueryMetadata(query, queryId, ruleId) or + isSideEffects2QueryMetadata(query, queryId, ruleId) or + isSmartPointers1QueryMetadata(query, queryId, ruleId) or + isSmartPointers2QueryMetadata(query, queryId, ruleId) or + isStringsQueryMetadata(query, queryId, ruleId) or + isTemplatesQueryMetadata(query, queryId, ruleId) or + isToolchainQueryMetadata(query, queryId, ruleId) or + isTrustBoundariesQueryMetadata(query, queryId, ruleId) or + isTypeRangesQueryMetadata(query, queryId, ruleId) or + isUninitializedQueryMetadata(query, queryId, ruleId) or + isVirtualFunctionsQueryMetadata(query, queryId, ruleId) +} diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Scope.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Scope.qll similarity index 86% rename from cpp/common/src/codingstandards/cpp/exclusions/Scope.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Scope.qll index 181c6f6900..0157347d3b 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Scope.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Scope.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ScopeQuery = TNonStandardEntitiesInStandardNamespacesQuery() or @@ -164,118 +165,118 @@ module ScopePackage { //autogenerate `Query` type result = // `Query` type for `nonStandardEntitiesInStandardNamespaces` query - TScopePackageQuery(TNonStandardEntitiesInStandardNamespacesQuery()) + TQueryCPP(TScopePackageQuery(TNonStandardEntitiesInStandardNamespacesQuery())) } Query externalLinkageArrayWithoutExplicitSizeQuery() { //autogenerate `Query` type result = // `Query` type for `externalLinkageArrayWithoutExplicitSize` query - TScopePackageQuery(TExternalLinkageArrayWithoutExplicitSizeQuery()) + TQueryCPP(TScopePackageQuery(TExternalLinkageArrayWithoutExplicitSizeQuery())) } Query hiddenInheritedNonOverridableMemberFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `hiddenInheritedNonOverridableMemberFunction` query - TScopePackageQuery(THiddenInheritedNonOverridableMemberFunctionQuery()) + TQueryCPP(TScopePackageQuery(THiddenInheritedNonOverridableMemberFunctionQuery())) } Query hiddenInheritedOverridableMemberFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `hiddenInheritedOverridableMemberFunction` query - TScopePackageQuery(THiddenInheritedOverridableMemberFunctionQuery()) + TQueryCPP(TScopePackageQuery(THiddenInheritedOverridableMemberFunctionQuery())) } Query definitionNotConsideredForUnqualifiedLookupQuery() { //autogenerate `Query` type result = // `Query` type for `definitionNotConsideredForUnqualifiedLookup` query - TScopePackageQuery(TDefinitionNotConsideredForUnqualifiedLookupQuery()) + TQueryCPP(TScopePackageQuery(TDefinitionNotConsideredForUnqualifiedLookupQuery())) } Query oneDefinitionRuleViolationQuery() { //autogenerate `Query` type result = // `Query` type for `oneDefinitionRuleViolation` query - TScopePackageQuery(TOneDefinitionRuleViolationQuery()) + TQueryCPP(TScopePackageQuery(TOneDefinitionRuleViolationQuery())) } Query multipleDeclarationViolationQuery() { //autogenerate `Query` type result = // `Query` type for `multipleDeclarationViolation` query - TScopePackageQuery(TMultipleDeclarationViolationQuery()) + TQueryCPP(TScopePackageQuery(TMultipleDeclarationViolationQuery())) } Query identifierWithExternalLinkageShallHaveOneDefinitionQuery() { //autogenerate `Query` type result = // `Query` type for `identifierWithExternalLinkageShallHaveOneDefinition` query - TScopePackageQuery(TIdentifierWithExternalLinkageShallHaveOneDefinitionQuery()) + TQueryCPP(TScopePackageQuery(TIdentifierWithExternalLinkageShallHaveOneDefinitionQuery())) } Query missingStaticSpecifierOnFunctionRedeclarationQuery() { //autogenerate `Query` type result = // `Query` type for `missingStaticSpecifierOnFunctionRedeclaration` query - TScopePackageQuery(TMissingStaticSpecifierOnFunctionRedeclarationQuery()) + TQueryCPP(TScopePackageQuery(TMissingStaticSpecifierOnFunctionRedeclarationQuery())) } Query unnecessaryExposedIdentifierDeclarationQuery() { //autogenerate `Query` type result = // `Query` type for `unnecessaryExposedIdentifierDeclaration` query - TScopePackageQuery(TUnnecessaryExposedIdentifierDeclarationQuery()) + TQueryCPP(TScopePackageQuery(TUnnecessaryExposedIdentifierDeclarationQuery())) } Query globalNamespaceMembershipViolationQuery() { //autogenerate `Query` type result = // `Query` type for `globalNamespaceMembershipViolation` query - TScopePackageQuery(TGlobalNamespaceMembershipViolationQuery()) + TQueryCPP(TScopePackageQuery(TGlobalNamespaceMembershipViolationQuery())) } Query localFunctionDeclarationQuery() { //autogenerate `Query` type result = // `Query` type for `localFunctionDeclaration` query - TScopePackageQuery(TLocalFunctionDeclarationQuery()) + TQueryCPP(TScopePackageQuery(TLocalFunctionDeclarationQuery())) } Query localConstructorInitializedObjectHidesIdentifierQuery() { //autogenerate `Query` type result = // `Query` type for `localConstructorInitializedObjectHidesIdentifier` query - TScopePackageQuery(TLocalConstructorInitializedObjectHidesIdentifierQuery()) + TQueryCPP(TScopePackageQuery(TLocalConstructorInitializedObjectHidesIdentifierQuery())) } Query singularOverloadOfMemoryFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `singularOverloadOfMemoryFunction` query - TScopePackageQuery(TSingularOverloadOfMemoryFunctionQuery()) + TQueryCPP(TScopePackageQuery(TSingularOverloadOfMemoryFunctionQuery())) } Query modificationOfTheStandardNamespacesQuery() { //autogenerate `Query` type result = // `Query` type for `modificationOfTheStandardNamespaces` query - TScopePackageQuery(TModificationOfTheStandardNamespacesQuery()) + TQueryCPP(TScopePackageQuery(TModificationOfTheStandardNamespacesQuery())) } Query unnamedNamespaceInHeaderFileQuery() { //autogenerate `Query` type result = // `Query` type for `unnamedNamespaceInHeaderFile` query - TScopePackageQuery(TUnnamedNamespaceInHeaderFileQuery()) + TQueryCPP(TScopePackageQuery(TUnnamedNamespaceInHeaderFileQuery())) } Query oneDefinitionRuleNotObeyedQuery() { //autogenerate `Query` type result = // `Query` type for `oneDefinitionRuleNotObeyed` query - TScopePackageQuery(TOneDefinitionRuleNotObeyedQuery()) + TQueryCPP(TScopePackageQuery(TOneDefinitionRuleNotObeyedQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/SideEffects1.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SideEffects1.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/SideEffects1.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/SideEffects1.qll index e5619f14de..03a0ea4f70 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/SideEffects1.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SideEffects1.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype SideEffects1Query = TEvaluationOfTheOperandToTheTypeidOperatorContainSideEffectsQuery() or @@ -101,69 +102,69 @@ module SideEffects1Package { //autogenerate `Query` type result = // `Query` type for `evaluationOfTheOperandToTheTypeidOperatorContainSideEffects` query - TSideEffects1PackageQuery(TEvaluationOfTheOperandToTheTypeidOperatorContainSideEffectsQuery()) + TQueryCPP(TSideEffects1PackageQuery(TEvaluationOfTheOperandToTheTypeidOperatorContainSideEffectsQuery())) } Query rightHandOperandOfALogicalAndOperatorsContainSideEffectsQuery() { //autogenerate `Query` type result = // `Query` type for `rightHandOperandOfALogicalAndOperatorsContainSideEffects` query - TSideEffects1PackageQuery(TRightHandOperandOfALogicalAndOperatorsContainSideEffectsQuery()) + TQueryCPP(TSideEffects1PackageQuery(TRightHandOperandOfALogicalAndOperatorsContainSideEffectsQuery())) } Query evaluationOfTheOperandToTheSizeofOperatorContainSideEffectsQuery() { //autogenerate `Query` type result = // `Query` type for `evaluationOfTheOperandToTheSizeofOperatorContainSideEffects` query - TSideEffects1PackageQuery(TEvaluationOfTheOperandToTheSizeofOperatorContainSideEffectsQuery()) + TQueryCPP(TSideEffects1PackageQuery(TEvaluationOfTheOperandToTheSizeofOperatorContainSideEffectsQuery())) } Query doNotDependOnTheOrderOfScalarObjectEvaluationForSideEffectsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotDependOnTheOrderOfScalarObjectEvaluationForSideEffects` query - TSideEffects1PackageQuery(TDoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffectsQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotDependOnTheOrderOfScalarObjectEvaluationForSideEffectsQuery())) } Query doNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArgumentsQuery() { //autogenerate `Query` type result = // `Query` type for `doNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArguments` query - TSideEffects1PackageQuery(TDoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArgumentsQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotDependOnTheOrderOfEvaluationForSideEffectsInFunctionCallsAsFunctionArgumentsQuery())) } Query doNotRelyOnSideEffectsInSizeOfOperandQuery() { //autogenerate `Query` type result = // `Query` type for `doNotRelyOnSideEffectsInSizeOfOperand` query - TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInSizeOfOperandQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInSizeOfOperandQuery())) } Query doNotRelyOnSideEffectsInTypeIdOperandQuery() { //autogenerate `Query` type result = // `Query` type for `doNotRelyOnSideEffectsInTypeIdOperand` query - TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInTypeIdOperandQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInTypeIdOperandQuery())) } Query doNotRelyOnSideEffectsInNoExceptOperandQuery() { //autogenerate `Query` type result = // `Query` type for `doNotRelyOnSideEffectsInNoExceptOperand` query - TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInNoExceptOperandQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInNoExceptOperandQuery())) } Query doNotRelyOnSideEffectsInDeclTypeOperandQuery() { //autogenerate `Query` type result = // `Query` type for `doNotRelyOnSideEffectsInDeclTypeOperand` query - TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInDeclTypeOperandQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInDeclTypeOperandQuery())) } Query doNotRelyOnSideEffectsInDeclValExpressionQuery() { //autogenerate `Query` type result = // `Query` type for `doNotRelyOnSideEffectsInDeclValExpression` query - TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInDeclValExpressionQuery()) + TQueryCPP(TSideEffects1PackageQuery(TDoNotRelyOnSideEffectsInDeclValExpressionQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/SideEffects2.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SideEffects2.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/SideEffects2.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/SideEffects2.qll index b5b0169756..ba930c214c 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/SideEffects2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SideEffects2.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype SideEffects2Query = TMoveConstructorShallOnlyMoveObjectQuery() or @@ -92,62 +93,62 @@ module SideEffects2Package { //autogenerate `Query` type result = // `Query` type for `moveConstructorShallOnlyMoveObject` query - TSideEffects2PackageQuery(TMoveConstructorShallOnlyMoveObjectQuery()) + TQueryCPP(TSideEffects2PackageQuery(TMoveConstructorShallOnlyMoveObjectQuery())) } Query copyConstructorShallOnlyCopyObjectQuery() { //autogenerate `Query` type result = // `Query` type for `copyConstructorShallOnlyCopyObject` query - TSideEffects2PackageQuery(TCopyConstructorShallOnlyCopyObjectQuery()) + TQueryCPP(TSideEffects2PackageQuery(TCopyConstructorShallOnlyCopyObjectQuery())) } Query userDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParametersQuery() { //autogenerate `Query` type result = // `Query` type for `userDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParameters` query - TSideEffects2PackageQuery(TUserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParametersQuery()) + TQueryCPP(TSideEffects2PackageQuery(TUserDefinedLiteralsOperatorsShallOnlyPerformConversionOfPassedParametersQuery())) } Query userDefinedLiteralsOperatorsShallNotHaveSideEffectsQuery() { //autogenerate `Query` type result = // `Query` type for `userDefinedLiteralsOperatorsShallNotHaveSideEffects` query - TSideEffects2PackageQuery(TUserDefinedLiteralsOperatorsShallNotHaveSideEffectsQuery()) + TQueryCPP(TSideEffects2PackageQuery(TUserDefinedLiteralsOperatorsShallNotHaveSideEffectsQuery())) } Query stateRelatedToFunctionObjectIdentityShallNotBeCopiedQuery() { //autogenerate `Query` type result = // `Query` type for `stateRelatedToFunctionObjectIdentityShallNotBeCopied` query - TSideEffects2PackageQuery(TStateRelatedToFunctionObjectIdentityShallNotBeCopiedQuery()) + TQueryCPP(TSideEffects2PackageQuery(TStateRelatedToFunctionObjectIdentityShallNotBeCopiedQuery())) } Query moveOperatorShallOnlyMoveObjectQuery() { //autogenerate `Query` type result = // `Query` type for `moveOperatorShallOnlyMoveObject` query - TSideEffects2PackageQuery(TMoveOperatorShallOnlyMoveObjectQuery()) + TQueryCPP(TSideEffects2PackageQuery(TMoveOperatorShallOnlyMoveObjectQuery())) } Query copyOperatorShallOnlyCopyObjectQuery() { //autogenerate `Query` type result = // `Query` type for `copyOperatorShallOnlyCopyObject` query - TSideEffects2PackageQuery(TCopyOperatorShallOnlyCopyObjectQuery()) + TQueryCPP(TSideEffects2PackageQuery(TCopyOperatorShallOnlyCopyObjectQuery())) } Query functionsWithVoidReturnTypeShallHaveExternalSideEffectsQuery() { //autogenerate `Query` type result = // `Query` type for `functionsWithVoidReturnTypeShallHaveExternalSideEffects` query - TSideEffects2PackageQuery(TFunctionsWithVoidReturnTypeShallHaveExternalSideEffectsQuery()) + TQueryCPP(TSideEffects2PackageQuery(TFunctionsWithVoidReturnTypeShallHaveExternalSideEffectsQuery())) } Query predicateFunctionObjectsShouldNotBeMutableQuery() { //autogenerate `Query` type result = // `Query` type for `predicateFunctionObjectsShouldNotBeMutable` query - TSideEffects2PackageQuery(TPredicateFunctionObjectsShouldNotBeMutableQuery()) + TQueryCPP(TSideEffects2PackageQuery(TPredicateFunctionObjectsShouldNotBeMutableQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/SmartPointers1.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SmartPointers1.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/SmartPointers1.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/SmartPointers1.qll index 07ed035a28..7750c2396b 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/SmartPointers1.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SmartPointers1.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype SmartPointers1Query = TOwnedPointerValueStoredInUnrelatedSmartPointerAsarQuery() or @@ -92,62 +93,62 @@ module SmartPointers1Package { //autogenerate `Query` type result = // `Query` type for `ownedPointerValueStoredInUnrelatedSmartPointerAsar` query - TSmartPointers1PackageQuery(TOwnedPointerValueStoredInUnrelatedSmartPointerAsarQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TOwnedPointerValueStoredInUnrelatedSmartPointerAsarQuery())) } Query uniquePtrNotUsedToRepresentExclusiveOwnershipQuery() { //autogenerate `Query` type result = // `Query` type for `uniquePtrNotUsedToRepresentExclusiveOwnership` query - TSmartPointers1PackageQuery(TUniquePtrNotUsedToRepresentExclusiveOwnershipQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TUniquePtrNotUsedToRepresentExclusiveOwnershipQuery())) } Query sharedPtrNotUsedToRepresentSharedOwnershipQuery() { //autogenerate `Query` type result = // `Query` type for `sharedPtrNotUsedToRepresentSharedOwnership` query - TSmartPointers1PackageQuery(TSharedPtrNotUsedToRepresentSharedOwnershipQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TSharedPtrNotUsedToRepresentSharedOwnershipQuery())) } Query sharedPointerUsedWithNoOwnershipSharingQuery() { //autogenerate `Query` type result = // `Query` type for `sharedPointerUsedWithNoOwnershipSharing` query - TSmartPointers1PackageQuery(TSharedPointerUsedWithNoOwnershipSharingQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TSharedPointerUsedWithNoOwnershipSharingQuery())) } Query makeUniqueNotUsedToConstructObjectOwnedByUniquePtrQuery() { //autogenerate `Query` type result = // `Query` type for `makeUniqueNotUsedToConstructObjectOwnedByUniquePtr` query - TSmartPointers1PackageQuery(TMakeUniqueNotUsedToConstructObjectOwnedByUniquePtrQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TMakeUniqueNotUsedToConstructObjectOwnedByUniquePtrQuery())) } Query makeSharedNotUsedToConstructObjectOwnedBySharedPtrQuery() { //autogenerate `Query` type result = // `Query` type for `makeSharedNotUsedToConstructObjectOwnedBySharedPtr` query - TSmartPointers1PackageQuery(TMakeSharedNotUsedToConstructObjectOwnedBySharedPtrQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TMakeSharedNotUsedToConstructObjectOwnedBySharedPtrQuery())) } Query smartPointerAsParameterWithoutLifetimeSemanticsQuery() { //autogenerate `Query` type result = // `Query` type for `smartPointerAsParameterWithoutLifetimeSemantics` query - TSmartPointers1PackageQuery(TSmartPointerAsParameterWithoutLifetimeSemanticsQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TSmartPointerAsParameterWithoutLifetimeSemanticsQuery())) } Query uniquePtrPassedToFunctionWithImproperSemanticsQuery() { //autogenerate `Query` type result = // `Query` type for `uniquePtrPassedToFunctionWithImproperSemantics` query - TSmartPointers1PackageQuery(TUniquePtrPassedToFunctionWithImproperSemanticsQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TUniquePtrPassedToFunctionWithImproperSemanticsQuery())) } Query sharedPtrPassedToFunctionWithImproperSemanticsQuery() { //autogenerate `Query` type result = // `Query` type for `sharedPtrPassedToFunctionWithImproperSemantics` query - TSmartPointers1PackageQuery(TSharedPtrPassedToFunctionWithImproperSemanticsQuery()) + TQueryCPP(TSmartPointers1PackageQuery(TSharedPtrPassedToFunctionWithImproperSemanticsQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/SmartPointers2.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SmartPointers2.qll similarity index 82% rename from cpp/common/src/codingstandards/cpp/exclusions/SmartPointers2.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/SmartPointers2.qll index e4084b784b..a64b418f2d 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/SmartPointers2.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/SmartPointers2.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype SmartPointers2Query = TWeakPtrNotUsedToRepresentTemporarySharedOwnershipQuery() or @@ -29,13 +30,13 @@ module SmartPointers2Package { //autogenerate `Query` type result = // `Query` type for `weakPtrNotUsedToRepresentTemporarySharedOwnership` query - TSmartPointers2PackageQuery(TWeakPtrNotUsedToRepresentTemporarySharedOwnershipQuery()) + TQueryCPP(TSmartPointers2PackageQuery(TWeakPtrNotUsedToRepresentTemporarySharedOwnershipQuery())) } Query ownedPointerValueStoredInUnrelatedSmartPointerCertQuery() { //autogenerate `Query` type result = // `Query` type for `ownedPointerValueStoredInUnrelatedSmartPointerCert` query - TSmartPointers2PackageQuery(TOwnedPointerValueStoredInUnrelatedSmartPointerCertQuery()) + TQueryCPP(TSmartPointers2PackageQuery(TOwnedPointerValueStoredInUnrelatedSmartPointerCertQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Strings.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Strings.qll similarity index 86% rename from cpp/common/src/codingstandards/cpp/exclusions/Strings.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Strings.qll index 71e2d3e582..457bac01b7 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Strings.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Strings.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype StringsQuery = TStringLiteralsAssignedToNonConstantPointersQuery() or @@ -83,55 +84,55 @@ module StringsPackage { //autogenerate `Query` type result = // `Query` type for `stringLiteralsAssignedToNonConstantPointers` query - TStringsPackageQuery(TStringLiteralsAssignedToNonConstantPointersQuery()) + TQueryCPP(TStringsPackageQuery(TStringLiteralsAssignedToNonConstantPointersQuery())) } Query basicStringMayNotBeNullTerminatedAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `basicStringMayNotBeNullTerminatedAutosar` query - TStringsPackageQuery(TBasicStringMayNotBeNullTerminatedAutosarQuery()) + TQueryCPP(TStringsPackageQuery(TBasicStringMayNotBeNullTerminatedAutosarQuery())) } Query operationMayNotNullTerminateCStyleStringAutosarQuery() { //autogenerate `Query` type result = // `Query` type for `operationMayNotNullTerminateCStyleStringAutosar` query - TStringsPackageQuery(TOperationMayNotNullTerminateCStyleStringAutosarQuery()) + TQueryCPP(TStringsPackageQuery(TOperationMayNotNullTerminateCStyleStringAutosarQuery())) } Query cStyleStringsUsedQuery() { //autogenerate `Query` type result = // `Query` type for `cStyleStringsUsed` query - TStringsPackageQuery(TCStyleStringsUsedQuery()) + TQueryCPP(TStringsPackageQuery(TCStyleStringsUsedQuery())) } Query plainCharTypeShallOnlyBeUsedForTheStorageAndUseOfCharacterValuesQuery() { //autogenerate `Query` type result = // `Query` type for `plainCharTypeShallOnlyBeUsedForTheStorageAndUseOfCharacterValues` query - TStringsPackageQuery(TPlainCharTypeShallOnlyBeUsedForTheStorageAndUseOfCharacterValuesQuery()) + TQueryCPP(TStringsPackageQuery(TPlainCharTypeShallOnlyBeUsedForTheStorageAndUseOfCharacterValuesQuery())) } Query signedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery() { //autogenerate `Query` type result = // `Query` type for `signedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues` query - TStringsPackageQuery(TSignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery()) + TQueryCPP(TStringsPackageQuery(TSignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery())) } Query basicStringMayNotBeNullTerminatedCertQuery() { //autogenerate `Query` type result = // `Query` type for `basicStringMayNotBeNullTerminatedCert` query - TStringsPackageQuery(TBasicStringMayNotBeNullTerminatedCertQuery()) + TQueryCPP(TStringsPackageQuery(TBasicStringMayNotBeNullTerminatedCertQuery())) } Query operationMayNotNullTerminateCStyleStringCertQuery() { //autogenerate `Query` type result = // `Query` type for `operationMayNotNullTerminateCStyleStringCert` query - TStringsPackageQuery(TOperationMayNotNullTerminateCStyleStringCertQuery()) + TQueryCPP(TStringsPackageQuery(TOperationMayNotNullTerminateCStyleStringCertQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Templates.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Templates.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Templates.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Templates.qll index 98c4926c93..5ad07851ab 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Templates.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Templates.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype TemplatesQuery = TTemplateShouldCheckArgQuery() or @@ -83,55 +84,55 @@ module TemplatesPackage { //autogenerate `Query` type result = // `Query` type for `templateShouldCheckArg` query - TTemplatesPackageQuery(TTemplateShouldCheckArgQuery()) + TQueryCPP(TTemplatesPackageQuery(TTemplateShouldCheckArgQuery())) } Query templateConstructorOverloadResolutionQuery() { //autogenerate `Query` type result = // `Query` type for `templateConstructorOverloadResolution` query - TTemplatesPackageQuery(TTemplateConstructorOverloadResolutionQuery()) + TQueryCPP(TTemplatesPackageQuery(TTemplateConstructorOverloadResolutionQuery())) } Query typeUsedAsTemplateArgShallProvideAllMembersQuery() { //autogenerate `Query` type result = // `Query` type for `typeUsedAsTemplateArgShallProvideAllMembers` query - TTemplatesPackageQuery(TTypeUsedAsTemplateArgShallProvideAllMembersQuery()) + TQueryCPP(TTemplatesPackageQuery(TTypeUsedAsTemplateArgShallProvideAllMembersQuery())) } Query templateSpecializationNotDeclaredInTheSameFileQuery() { //autogenerate `Query` type result = // `Query` type for `templateSpecializationNotDeclaredInTheSameFile` query - TTemplatesPackageQuery(TTemplateSpecializationNotDeclaredInTheSameFileQuery()) + TQueryCPP(TTemplatesPackageQuery(TTemplateSpecializationNotDeclaredInTheSameFileQuery())) } Query explicitSpecializationsOfFunctionTemplatesUsedQuery() { //autogenerate `Query` type result = // `Query` type for `explicitSpecializationsOfFunctionTemplatesUsed` query - TTemplatesPackageQuery(TExplicitSpecializationsOfFunctionTemplatesUsedQuery()) + TQueryCPP(TTemplatesPackageQuery(TExplicitSpecializationsOfFunctionTemplatesUsedQuery())) } Query copyAssignmentOperatorNotDeclaredQuery() { //autogenerate `Query` type result = // `Query` type for `copyAssignmentOperatorNotDeclared` query - TTemplatesPackageQuery(TCopyAssignmentOperatorNotDeclaredQuery()) + TQueryCPP(TTemplatesPackageQuery(TCopyAssignmentOperatorNotDeclaredQuery())) } Query nameNotReferredUsingAQualifiedIdOrThisQuery() { //autogenerate `Query` type result = // `Query` type for `nameNotReferredUsingAQualifiedIdOrThis` query - TTemplatesPackageQuery(TNameNotReferredUsingAQualifiedIdOrThisQuery()) + TQueryCPP(TTemplatesPackageQuery(TNameNotReferredUsingAQualifiedIdOrThisQuery())) } Query nameNotReferredUsingAQualifiedIdOrThisAuditQuery() { //autogenerate `Query` type result = // `Query` type for `nameNotReferredUsingAQualifiedIdOrThisAudit` query - TTemplatesPackageQuery(TNameNotReferredUsingAQualifiedIdOrThisAuditQuery()) + TQueryCPP(TTemplatesPackageQuery(TNameNotReferredUsingAQualifiedIdOrThisAuditQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Toolchain.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Toolchain.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/Toolchain.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Toolchain.qll index 62e4875e76..969405c785 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Toolchain.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Toolchain.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype ToolchainQuery = TFloatingPointImplementationShallComplyWithIeeeStandardQuery() or @@ -110,76 +111,76 @@ module ToolchainPackage { //autogenerate `Query` type result = // `Query` type for `floatingPointImplementationShallComplyWithIeeeStandard` query - TToolchainPackageQuery(TFloatingPointImplementationShallComplyWithIeeeStandardQuery()) + TQueryCPP(TToolchainPackageQuery(TFloatingPointImplementationShallComplyWithIeeeStandardQuery())) } Query compilerImplementationShallComplyWithCPP14StandardQuery() { //autogenerate `Query` type result = // `Query` type for `compilerImplementationShallComplyWithCPP14Standard` query - TToolchainPackageQuery(TCompilerImplementationShallComplyWithCPP14StandardQuery()) + TQueryCPP(TToolchainPackageQuery(TCompilerImplementationShallComplyWithCPP14StandardQuery())) } Query incrementOperatorWithBoolOperandIsDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `incrementOperatorWithBoolOperandIsDeprecated` query - TToolchainPackageQuery(TIncrementOperatorWithBoolOperandIsDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TIncrementOperatorWithBoolOperandIsDeprecatedQuery())) } Query registerKeywordIsDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `registerKeywordIsDeprecated` query - TToolchainPackageQuery(TRegisterKeywordIsDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TRegisterKeywordIsDeprecatedQuery())) } Query implicitCopyConstructorIsDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `implicitCopyConstructorIsDeprecated` query - TToolchainPackageQuery(TImplicitCopyConstructorIsDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TImplicitCopyConstructorIsDeprecatedQuery())) } Query implicitCopyAssignmentOperatorIsDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `implicitCopyAssignmentOperatorIsDeprecated` query - TToolchainPackageQuery(TImplicitCopyAssignmentOperatorIsDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TImplicitCopyAssignmentOperatorIsDeprecatedQuery())) } Query dynamicExceptionsAreDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `dynamicExceptionsAreDeprecated` query - TToolchainPackageQuery(TDynamicExceptionsAreDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TDynamicExceptionsAreDeprecatedQuery())) } Query cStandardLibraryHeadersAreDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `cStandardLibraryHeadersAreDeprecated` query - TToolchainPackageQuery(TCStandardLibraryHeadersAreDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TCStandardLibraryHeadersAreDeprecatedQuery())) } Query strstreamTypesAreDeprecatedQuery() { //autogenerate `Query` type result = // `Query` type for `strstreamTypesAreDeprecated` query - TToolchainPackageQuery(TStrstreamTypesAreDeprecatedQuery()) + TQueryCPP(TToolchainPackageQuery(TStrstreamTypesAreDeprecatedQuery())) } Query compilerWarningLevelNotInComplianceQuery() { //autogenerate `Query` type result = // `Query` type for `compilerWarningLevelNotInCompliance` query - TToolchainPackageQuery(TCompilerWarningLevelNotInComplianceQuery()) + TQueryCPP(TToolchainPackageQuery(TCompilerWarningLevelNotInComplianceQuery())) } Query uncompliantOptimizationOptionMustBeDisabledInCompilerQuery() { //autogenerate `Query` type result = // `Query` type for `uncompliantOptimizationOptionMustBeDisabledInCompiler` query - TToolchainPackageQuery(TUncompliantOptimizationOptionMustBeDisabledInCompilerQuery()) + TQueryCPP(TToolchainPackageQuery(TUncompliantOptimizationOptionMustBeDisabledInCompilerQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/TrustBoundaries.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/TrustBoundaries.qll similarity index 82% rename from cpp/common/src/codingstandards/cpp/exclusions/TrustBoundaries.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/TrustBoundaries.qll index d6d18ddb62..b6135deba8 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/TrustBoundaries.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/TrustBoundaries.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype TrustBoundariesQuery = TExceptionsThrownAcrossExecutionBoundariesQuery() or @@ -38,20 +39,20 @@ module TrustBoundariesPackage { //autogenerate `Query` type result = // `Query` type for `exceptionsThrownAcrossExecutionBoundaries` query - TTrustBoundariesPackageQuery(TExceptionsThrownAcrossExecutionBoundariesQuery()) + TQueryCPP(TTrustBoundariesPackageQuery(TExceptionsThrownAcrossExecutionBoundariesQuery())) } Query doNotThrowAnExceptionAcrossExecutionBoundariesQuery() { //autogenerate `Query` type result = // `Query` type for `doNotThrowAnExceptionAcrossExecutionBoundaries` query - TTrustBoundariesPackageQuery(TDoNotThrowAnExceptionAcrossExecutionBoundariesQuery()) + TQueryCPP(TTrustBoundariesPackageQuery(TDoNotThrowAnExceptionAcrossExecutionBoundariesQuery())) } Query doNotPassANonstandardObjectAcrossBoundariesQuery() { //autogenerate `Query` type result = // `Query` type for `doNotPassANonstandardObjectAcrossBoundaries` query - TTrustBoundariesPackageQuery(TDoNotPassANonstandardObjectAcrossBoundariesQuery()) + TQueryCPP(TTrustBoundariesPackageQuery(TDoNotPassANonstandardObjectAcrossBoundariesQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/TypeRanges.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/TypeRanges.qll similarity index 85% rename from cpp/common/src/codingstandards/cpp/exclusions/TypeRanges.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/TypeRanges.qll index 2704c21ea7..5104a03793 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/TypeRanges.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/TypeRanges.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype TypeRangesQuery = TUncheckedRangeDomainPoleErrorsQuery() or @@ -101,69 +102,69 @@ module TypeRangesPackage { //autogenerate `Query` type result = // `Query` type for `uncheckedRangeDomainPoleErrors` query - TTypeRangesPackageQuery(TUncheckedRangeDomainPoleErrorsQuery()) + TQueryCPP(TTypeRangesPackageQuery(TUncheckedRangeDomainPoleErrorsQuery())) } Query stringNumberConversionMissingErrorCheckQuery() { //autogenerate `Query` type result = // `Query` type for `stringNumberConversionMissingErrorCheck` query - TTypeRangesPackageQuery(TStringNumberConversionMissingErrorCheckQuery()) + TQueryCPP(TTypeRangesPackageQuery(TStringNumberConversionMissingErrorCheckQuery())) } Query useOfUnsafeCStringToNumberConversionQuery() { //autogenerate `Query` type result = // `Query` type for `useOfUnsafeCStringToNumberConversion` query - TTypeRangesPackageQuery(TUseOfUnsafeCStringToNumberConversionQuery()) + TQueryCPP(TTypeRangesPackageQuery(TUseOfUnsafeCStringToNumberConversionQuery())) } Query signedValPassedToCharQuery() { //autogenerate `Query` type result = // `Query` type for `signedValPassedToChar` query - TTypeRangesPackageQuery(TSignedValPassedToCharQuery()) + TQueryCPP(TTypeRangesPackageQuery(TSignedValPassedToCharQuery())) } Query inputsFromIndependentComponentsNotValidatedQuery() { //autogenerate `Query` type result = // `Query` type for `inputsFromIndependentComponentsNotValidated` query - TTypeRangesPackageQuery(TInputsFromIndependentComponentsNotValidatedQuery()) + TQueryCPP(TTypeRangesPackageQuery(TInputsFromIndependentComponentsNotValidatedQuery())) } Query nonEnumeratorEnumValueQuery() { //autogenerate `Query` type result = // `Query` type for `nonEnumeratorEnumValue` query - TTypeRangesPackageQuery(TNonEnumeratorEnumValueQuery()) + TQueryCPP(TTypeRangesPackageQuery(TNonEnumeratorEnumValueQuery())) } Query useOfEnumForRelatedConstantsQuery() { //autogenerate `Query` type result = // `Query` type for `useOfEnumForRelatedConstants` query - TTypeRangesPackageQuery(TUseOfEnumForRelatedConstantsQuery()) + TQueryCPP(TTypeRangesPackageQuery(TUseOfEnumForRelatedConstantsQuery())) } Query integerUsedForEnumQuery() { //autogenerate `Query` type result = // `Query` type for `integerUsedForEnum` query - TTypeRangesPackageQuery(TIntegerUsedForEnumQuery()) + TQueryCPP(TTypeRangesPackageQuery(TIntegerUsedForEnumQuery())) } Query detectErrorsWhenConvertingAStringToANumberQuery() { //autogenerate `Query` type result = // `Query` type for `detectErrorsWhenConvertingAStringToANumber` query - TTypeRangesPackageQuery(TDetectErrorsWhenConvertingAStringToANumberQuery()) + TQueryCPP(TTypeRangesPackageQuery(TDetectErrorsWhenConvertingAStringToANumberQuery())) } Query doNotCastToAnOutOfRangeEnumerationValueQuery() { //autogenerate `Query` type result = // `Query` type for `doNotCastToAnOutOfRangeEnumerationValue` query - TTypeRangesPackageQuery(TDoNotCastToAnOutOfRangeEnumerationValueQuery()) + TQueryCPP(TTypeRangesPackageQuery(TDoNotCastToAnOutOfRangeEnumerationValueQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/Uninitialized.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Uninitialized.qll similarity index 82% rename from cpp/common/src/codingstandards/cpp/exclusions/Uninitialized.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/Uninitialized.qll index 0f43f171cf..ce5e0ad2a0 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/Uninitialized.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/Uninitialized.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype UninitializedQuery = TMemoryNotInitializedBeforeItIsReadQuery() or @@ -38,20 +39,20 @@ module UninitializedPackage { //autogenerate `Query` type result = // `Query` type for `memoryNotInitializedBeforeItIsRead` query - TUninitializedPackageQuery(TMemoryNotInitializedBeforeItIsReadQuery()) + TQueryCPP(TUninitializedPackageQuery(TMemoryNotInitializedBeforeItIsReadQuery())) } Query informationLeakageAcrossTrustBoundariesQuery() { //autogenerate `Query` type result = // `Query` type for `informationLeakageAcrossTrustBoundaries` query - TUninitializedPackageQuery(TInformationLeakageAcrossTrustBoundariesQuery()) + TQueryCPP(TUninitializedPackageQuery(TInformationLeakageAcrossTrustBoundariesQuery())) } Query doNotReadUninitializedMemoryQuery() { //autogenerate `Query` type result = // `Query` type for `doNotReadUninitializedMemory` query - TUninitializedPackageQuery(TDoNotReadUninitializedMemoryQuery()) + TQueryCPP(TUninitializedPackageQuery(TDoNotReadUninitializedMemoryQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/exclusions/VirtualFunctions.qll b/cpp/common/src/codingstandards/cpp/exclusions/cpp/VirtualFunctions.qll similarity index 84% rename from cpp/common/src/codingstandards/cpp/exclusions/VirtualFunctions.qll rename to cpp/common/src/codingstandards/cpp/exclusions/cpp/VirtualFunctions.qll index ff1ad6e300..a55c48d4dd 100644 --- a/cpp/common/src/codingstandards/cpp/exclusions/VirtualFunctions.qll +++ b/cpp/common/src/codingstandards/cpp/exclusions/cpp/VirtualFunctions.qll @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype VirtualFunctionsQuery = TNonVirtualPublicOrProtectedFunctionsRedefinedQuery() or @@ -83,55 +84,55 @@ module VirtualFunctionsPackage { //autogenerate `Query` type result = // `Query` type for `nonVirtualPublicOrProtectedFunctionsRedefined` query - TVirtualFunctionsPackageQuery(TNonVirtualPublicOrProtectedFunctionsRedefinedQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TNonVirtualPublicOrProtectedFunctionsRedefinedQuery())) } Query virtualFunctionsShallContainOneSpecifierQuery() { //autogenerate `Query` type result = // `Query` type for `virtualFunctionsShallContainOneSpecifier` query - TVirtualFunctionsPackageQuery(TVirtualFunctionsShallContainOneSpecifierQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TVirtualFunctionsShallContainOneSpecifierQuery())) } Query overridingFunctionNotDeclaredOverrideOrFinalQuery() { //autogenerate `Query` type result = // `Query` type for `overridingFunctionNotDeclaredOverrideOrFinal` query - TVirtualFunctionsPackageQuery(TOverridingFunctionNotDeclaredOverrideOrFinalQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TOverridingFunctionNotDeclaredOverrideOrFinalQuery())) } Query virtualFunctionsIntroducedInFinalClassQuery() { //autogenerate `Query` type result = // `Query` type for `virtualFunctionsIntroducedInFinalClass` query - TVirtualFunctionsPackageQuery(TVirtualFunctionsIntroducedInFinalClassQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TVirtualFunctionsIntroducedInFinalClassQuery())) } Query destructorOfABaseClassNotPublicVirtualQuery() { //autogenerate `Query` type result = // `Query` type for `destructorOfABaseClassNotPublicVirtual` query - TVirtualFunctionsPackageQuery(TDestructorOfABaseClassNotPublicVirtualQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TDestructorOfABaseClassNotPublicVirtualQuery())) } Query nonVirtualPublicDestructorInNonFinalClassQuery() { //autogenerate `Query` type result = // `Query` type for `nonVirtualPublicDestructorInNonFinalClass` query - TVirtualFunctionsPackageQuery(TNonVirtualPublicDestructorInNonFinalClassQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TNonVirtualPublicDestructorInNonFinalClassQuery())) } Query virtualFunctionOverriddenByAPureVirtualFunctionQuery() { //autogenerate `Query` type result = // `Query` type for `virtualFunctionOverriddenByAPureVirtualFunction` query - TVirtualFunctionsPackageQuery(TVirtualFunctionOverriddenByAPureVirtualFunctionQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TVirtualFunctionOverriddenByAPureVirtualFunctionQuery())) } Query virtualFunctionParametersUseTheSameDefaultArgumentsQuery() { //autogenerate `Query` type result = // `Query` type for `virtualFunctionParametersUseTheSameDefaultArguments` query - TVirtualFunctionsPackageQuery(TVirtualFunctionParametersUseTheSameDefaultArgumentsQuery()) + TQueryCPP(TVirtualFunctionsPackageQuery(TVirtualFunctionParametersUseTheSameDefaultArgumentsQuery())) } } diff --git a/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll b/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll new file mode 100644 index 0000000000..41d7d9956d --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/donotaccessaclosedfile/DoNotAccessAClosedFile.qll @@ -0,0 +1,66 @@ +/** + * Provides a library which includes a `problems` predicate for reporting + * access to closed files + */ + +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.standardlibrary.FileAccess +import semmle.code.cpp.controlflow.SubBasicBlocks + +abstract class DoNotAccessAClosedFileSharedQuery extends Query { } + +Query getQuery() { result instanceof DoNotAccessAClosedFileSharedQuery } + +class ClosedFileAccessSubBasicBlock extends SubBasicBlockCutNode { + ClosedFileAccessSubBasicBlock() { + this instanceof VariableAccess or + this instanceof AssignExpr or + this instanceof FunctionCall + } +} + +pragma[inline] +predicate accessSameVariable(VariableAccess va1, VariableAccess va2) { + va1.getTarget() = va2.getTarget() +} + +SubBasicBlock followsFileClose(SubBasicBlock source, VariableAccess closedFile) { + result = source + or + exists(SubBasicBlock mid | + mid = followsFileClose(source, closedFile) and + result = mid.getASuccessor() and + //Stop recursion on reassignment of closedFile + not accessSameVariable(result.(AssignExpr).getLValue(), closedFile) + ) +} + +// the argument of a call to function `fclose(FILE*)` is subsequently accessed +predicate closedFileAccess(Expr closedFile, Expr fileAccess) { + exists(DataFlow::DefinitionByReferenceNode def | + def.asDefiningArgument() = closedFile and + DataFlow::localFlow(def, DataFlow::exprNode(fileAccess.(VariableAccess))) + ) +} + +query predicate problems( + Expr fileAccess, string message, FunctionCall closeFC, string closeFCDescription +) { + not isExcluded(fileAccess, getQuery()) and + exists(Expr closedFile | + fcloseCall(closeFC, closedFile) and + fileAccess = followsFileClose(closeFC, closedFile) and + ( + // implicit access to closed stdio/stderr/stdout + fileAccess.(ImplicitFileAccess).getFileExpr() = closedFile + or + // explicit access to a closed FILE object + closedFileAccess(closedFile, fileAccess) + ) and + message = "Access of closed file" + closedFile + "which was closed at $@" and + closeFCDescription = "this location." + ) +} diff --git a/cpp/common/src/codingstandards/cpp/rules/hashoperatorsused/HashOperatorsUsed.qll b/cpp/common/src/codingstandards/cpp/rules/hashoperatorsused/HashOperatorsUsed.qll new file mode 100644 index 0000000000..ae825e926f --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/hashoperatorsused/HashOperatorsUsed.qll @@ -0,0 +1,21 @@ +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions + +abstract class HashOperatorsUsedQuery extends Query { } + +Query getQuery() { result instanceof HashOperatorsUsedQuery } + +query predicate problems(Macro m, string message) { + exists(string body | + body = + m.getBody() + .regexpReplaceAll("\\\\\"", "") + .regexpReplaceAll("\\\\'", "") + .regexpReplaceAll("\"[^\"]+\"", "") + .regexpReplaceAll("'[^']+'", "") and + exists(int n | n = body.indexOf("#")) and + not isExcluded(m, getQuery()) and + message = "Macro definition uses the # or ## operator." + ) +} diff --git a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll index ff3b83e92d..fdfb8512ba 100644 --- a/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll +++ b/cpp/common/src/codingstandards/cpp/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.qll @@ -8,48 +8,89 @@ import cpp import semmle.code.cpp.dataflow.TaintTracking import codingstandards.cpp.Exclusions import codingstandards.cpp.standardlibrary.FileStreams +import codingstandards.cpp.standardlibrary.FileAccess abstract class IOFstreamMissingPositioningSharedQuery extends Query { } Query getQuery() { result instanceof IOFstreamMissingPositioningSharedQuery } -predicate sameStreamSource(FileStreamFunctionCall a, FileStreamFunctionCall b) { - exists(FileStreamSource c | - c.getAUse() = a.getFStream() and - c.getAUse() = b.getFStream() - ) +/** + * A Class modelling calls to file read and write functions. + */ +abstract class ReadWriteCall extends FunctionCall { + abstract string getAccessDirection(); + + abstract Expr getFStream(); +} + +class ReadFunctionCall extends ReadWriteCall { + ReadFunctionCall() { + this instanceof FileReadFunctionCall or + this instanceof ExtractionOperatorCall + } + + override string getAccessDirection() { result = "read" } + + override Expr getFStream() { + result = this.(FileReadFunctionCall).getFileExpr() or + result = this.(ExtractionOperatorCall).getFStream() + } } -predicate sameOperator(InExOperatorCall a, InExOperatorCall b) { a.getTarget() = b.getTarget() } +class WriteFunctionCall extends ReadWriteCall { + WriteFunctionCall() { + this instanceof FileWriteFunctionCall or + this instanceof InsertionOperatorCall + } -predicate oppositeOperator(InExOperatorCall a, InExOperatorCall b) { not sameOperator(a, b) } + override string getAccessDirection() { result = "write" } + + override Expr getFStream() { + result = this.(FileWriteFunctionCall).getFileExpr() or + result = this.(InsertionOperatorCall).getFStream() + } +} + +predicate sameSource(FunctionCall a, FunctionCall b) { + sameStreamSource(a, b) or + sameFileSource(a, b) +} + +predicate sameAccessDirection(ReadWriteCall a, ReadWriteCall b) { + a.getAccessDirection() = b.getAccessDirection() +} + +predicate oppositeAccessDirection(ReadWriteCall a, ReadWriteCall b) { + not sameAccessDirection(a, b) +} /** - * Insertion operator (`operator>>`) before extraction operator (`operator<<`) + * A write operation reaching a read and vice versa + * without intervening filepositioning */ -ControlFlowNode reachesInExOperator(InExOperatorCall op) { +ControlFlowNode reachesInExOperator(ReadWriteCall op) { result = op or exists(ControlFlowNode mid | mid = reachesInExOperator(op) and result = mid.getAPredecessor() and //Stop recursion after first occurrence of the opposite operator - not (oppositeOperator(mid, op) and sameStreamSource(mid, op)) and - //Stop recursion on seek function calls - not sameStreamSource(result.(SeekFunctionCall), op) and + not (oppositeAccessDirection(mid, op) and sameStreamSource(mid, op)) and + //Stop recursion on positioning function calls + not sameSource(result.(FileStreamPositioningCall), op) and + not sameSource(result.(FilePositioningFunctionCall), op) and //Stop recursion on same operator - not (sameOperator(result, op) and sameStreamSource(result, op)) + not (sameAccessDirection(result, op) and sameSource(result, op)) ) } query predicate problems( - InExOperatorCall fstOperator, string message, InExOperatorCall sndOperator, - string sndOperatorDescription + ReadWriteCall snd, string message, ReadWriteCall fst, string fstOperatorDescription ) { - not isExcluded(sndOperator, getQuery()) and - not sameOperator(fstOperator, sndOperator) and - sameStreamSource(fstOperator, sndOperator) and - fstOperator = reachesInExOperator(sndOperator) and + not isExcluded(snd, getQuery()) and + not sameAccessDirection(fst, snd) and + sameSource(fst, snd) and + fst = reachesInExOperator(snd) and message = "Missing call to positioning function before $@." and - sndOperatorDescription = sndOperator.toString() + fstOperatorDescription = snd.toString() } diff --git a/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll b/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll new file mode 100644 index 0000000000..34d6c4f3e4 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/nonconstantformat/NonConstantFormat.qll @@ -0,0 +1,136 @@ +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions +import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.commons.Printf + +abstract class NonConstantFormatSharedQuery extends Query { } + +Query getQuery() { result instanceof NonConstantFormatSharedQuery } + +// For the following `...gettext` functions, we assume that +// all translations preserve the type and order of `%` specifiers +// (and hence are safe to use as format strings). This +// assumption is hard-coded into the query. +predicate whitelistFunction(Function f, int arg) { + // basic variations of gettext + f.getName() = "_" and arg = 0 + or + f.getName() = "gettext" and arg = 0 + or + f.getName() = "dgettext" and arg = 1 + or + f.getName() = "dcgettext" and arg = 1 + or + // plural variations of gettext that take one format string for singular and another for plural form + f.getName() = "ngettext" and + (arg = 0 or arg = 1) + or + f.getName() = "dngettext" and + (arg = 1 or arg = 2) + or + f.getName() = "dcngettext" and + (arg = 1 or arg = 2) +} + +// we assume that ALL uses of the `_` macro +// return constant string literals +predicate underscoreMacro(Expr e) { + exists(MacroInvocation mi | + mi.getMacroName() = "_" and + mi.getExpr() = e + ) +} + +/** + * Holds if `t` cannot hold a character array, directly or indirectly. + */ +predicate cannotContainString(Type t) { + t.getUnspecifiedType() instanceof BuiltInType + or + t.getUnspecifiedType() instanceof IntegralOrEnumType +} + +predicate isNonConst(DataFlow::Node node) { + exists(Expr e | e = node.asExpr() | + exists(FunctionCall fc | fc = e.(FunctionCall) | + not ( + whitelistFunction(fc.getTarget(), _) or + fc.getTarget().hasDefinition() + ) + ) + or + exists(Parameter p | p = e.(VariableAccess).getTarget().(Parameter) | + p.getFunction().getName() = "main" and p.getType() instanceof PointerType + ) + or + e instanceof CrementOperation + or + e instanceof AddressOfExpr + or + e instanceof ReferenceToExpr + or + e instanceof AssignPointerAddExpr + or + e instanceof AssignPointerSubExpr + or + e instanceof PointerArithmeticOperation + or + e instanceof FieldAccess + or + e instanceof PointerDereferenceExpr + or + e instanceof AddressOfExpr + or + e instanceof ExprCall + or + e instanceof NewArrayExpr + or + e instanceof AssignExpr + or + exists(Variable v | v = e.(VariableAccess).getTarget() | + v.getType().(ArrayType).getBaseType() instanceof CharType and + exists(AssignExpr ae | + ae.getLValue().(ArrayExpr).getArrayBase().(VariableAccess).getTarget() = v + ) + ) + ) + or + node instanceof DataFlow::DefinitionByReferenceNode +} + +pragma[noinline] +predicate isSanitizerNode(DataFlow::Node node) { + underscoreMacro(node.asExpr()) + or + cannotContainString(node.getType()) +} + +class NonConstFlow extends TaintTracking::Configuration { + NonConstFlow() { this = "NonConstFlow" } + + override predicate isSource(DataFlow::Node source) { + isNonConst(source) and + not cannotContainString(source.getType()) + } + + override predicate isSink(DataFlow::Node sink) { + exists(FormattingFunctionCall fc | sink.asExpr() = fc.getArgument(fc.getFormatParameterIndex())) + } + + override predicate isSanitizer(DataFlow::Node node) { isSanitizerNode(node) } +} + +query predicate problems( + Expr formatString, string message, FormattingFunctionCall call, string formatStringDescription +) { + not isExcluded(formatString, getQuery()) and + call.getArgument(call.getFormatParameterIndex()) = formatString and + exists(NonConstFlow cf, DataFlow::Node source, DataFlow::Node sink | + cf.hasFlow(source, sink) and + sink.asExpr() = formatString + ) and + message = + "The format string argument to `$@` should be constant to prevent security issues and other potential errors." and + formatStringDescription = call.getTarget().getName() +} diff --git a/cpp/common/src/codingstandards/cpp/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.qll b/cpp/common/src/codingstandards/cpp/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.qll new file mode 100644 index 0000000000..deed463b7a --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.qll @@ -0,0 +1,19 @@ +import cpp +import codingstandards.cpp.Customizations +import codingstandards.cpp.Exclusions + +abstract class PreprocessorIncludesForbiddenHeaderNamesQuery extends Query { } + +Query getQuery() { result instanceof PreprocessorIncludesForbiddenHeaderNamesQuery } + +class InvalidInclude extends Include { + InvalidInclude() { this.getIncludeText().regexpMatch("[\"<].*(['\"\\\\]|\\/\\*|\\/\\/).*[\">]") } +} + +query predicate problems(Include i, string message) { + not isExcluded(i, getQuery()) and + i instanceof InvalidInclude and + message = + "The #include of " + i.getIncludeText() + + " contains a character sequence with implementation-defined behavior." +} diff --git a/cpp/common/src/codingstandards/cpp/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.qll b/cpp/common/src/codingstandards/cpp/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.qll new file mode 100644 index 0000000000..7e1d8f4a4a --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.qll @@ -0,0 +1,41 @@ +import cpp +import codingstandards.cpp.Exclusions + +abstract class PreprocessorIncludesPrecededSharedQuery extends Query { } + +Query getQuery() { result instanceof PreprocessorIncludesPrecededSharedQuery } + +class PreprocessorBranchMacroAccess extends MacroAccess { + PreprocessorBranchMacroAccess() { + // We're only interested in cases in the users source code + exists(getFile().getRelativePath()) and + exists(PreprocessorBranchDirective pd, string filepath, int startline | + pd.getLocation().hasLocationInfo(filepath, startline, _, _, _) and + getLocation().hasLocationInfo(filepath, startline, _, _, _) + ) + } +} + +class NotIncludeOrCommentElement extends Element { + NotIncludeOrCommentElement() { + exists(getFile().getRelativePath()) and + not ( + this instanceof PreprocessorDirective or + this instanceof Comment or + this instanceof File or + this instanceof PreprocessorBranchMacroAccess + ) + } +} + +query predicate problems(Include second, string message) { + exists(NotIncludeOrCommentElement first | + exists(string filepath, int firststartline, int secondstartline | + first.getLocation().hasLocationInfo(filepath, firststartline, _, _, _) and + second.getLocation().hasLocationInfo(filepath, secondstartline, _, _, _) and + firststartline < secondstartline + ) and + not isExcluded(second, getQuery()) and + message = second + " is preceded by a non-preprocessor or comment code element." + ) +} diff --git a/cpp/common/src/codingstandards/cpp/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.qll b/cpp/common/src/codingstandards/cpp/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.qll new file mode 100644 index 0000000000..00f2a66394 --- /dev/null +++ b/cpp/common/src/codingstandards/cpp/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.qll @@ -0,0 +1,121 @@ +import cpp +import codingstandards.cpp.Exclusions + +abstract class UndefinedMacroIdentifiersQuery extends Query { } + +Query getQuery() { result instanceof UndefinedMacroIdentifiersQuery } + +pragma[noinline] +predicate isMacroAccessFileAndLine(MacroAccess ma, string filepath, int startLine) { + ma.getLocation().hasLocationInfo(filepath, startLine, _, _, _) +} + +pragma[noinline] +predicate isPreprocFileAndLine(PreprocessorBranchDirective pd, string filepath, int startLine) { + pd.getLocation().hasLocationInfo(filepath, startLine, _, _, _) +} + +/** + * A `MacroAccess` that occurs in a `PreprocessorBranchDirective`. + * + * Example: + * ``` + * #if FOO_BAR != 30 + * ... + * ``` + */ +class PreprocessorBranchMacroAccess extends MacroAccess { + PreprocessorBranch pd; + + PreprocessorBranchMacroAccess() { + // We're only interested in cases in the users source code + exists(getFile().getRelativePath()) and + // There must a be a `PreprocessorBranch` that occurs in the same file, and on the + // same line + exists(string filepath, int startLine | + // Extracted to improve join order + isPreprocFileAndLine(pd, filepath, startLine) and + isMacroAccessFileAndLine(this, filepath, startLine) + ) + } + + PreprocessorBranch getBranchDirective() { result = pd } +} + +/** + * An optimised version of `PreprocessorBranchDirective.getAGuard()`. + */ +private PreprocessorBranch getAGuard(PreprocessorBranch pb) { + exists( + PreprocessorEndif end, string filepath, int guardStartLine, int pbStartLine, int endifStartLine + | + result.getEndIf() = end + | + isPreprocFileAndLine(result, filepath, guardStartLine) and + isPreprocFileAndLine(pb, filepath, pbStartLine) and + isPreprocFileAndLine(end, filepath, endifStartLine) and + guardStartLine < pbStartLine and + pbStartLine < endifStartLine + ) +} + +/** Gets a macro identifier which is #ifdef checked in `pb`. */ +string getAnIfDefdMacroIdentifier(PreprocessorBranch pb) { + exists(string portion | + portion = + pb.getHead() + .replaceAll("\\", " ") + .replaceAll("(", " ") + .replaceAll(")", " ") + .splitAt("&&") + .splitAt("||") and + result = portion.regexpCapture("^.*defined\\s*\\(?\\s*([a-zA-Z_][0-9a-zA-Z_]*)\\s*\\)?.*$", 1) + or + portion = "" and + pb.(PreprocessorIfdef).getHead() = result + ) +} + +class IfAndElifs extends PreprocessorBranch { + IfAndElifs() { + this instanceof PreprocessorIf or + this instanceof PreprocessorElif + } +} + +class BadIfAndElifs extends IfAndElifs { + string undefinedMacroIdentifier; + + BadIfAndElifs() { + exists(string defRM | + defRM = + this.getHead() + .regexpReplaceAll("__has_(attribute|cpp_attribute|c_attribute|builtin|include)\\s*\\(\\s*[0-9a-zA-Z_:]*\\s*\\)", + "") + .regexpReplaceAll("defined\\s*\\(?\\s*[a-zA-Z_][0-9a-zA-Z_]*\\s*\\)?", "") and + undefinedMacroIdentifier = defRM.regexpFind("(?>` operators. */ -abstract class InExOperator extends Operator { } +class InsertionOperatorCall extends FileStreamFunctionCall { + InsertionOperatorCall() { this.getTarget().(Operator).hasQualifiedName("std", "operator<<") } -class InsertionOperator extends InExOperator { - InsertionOperator() { hasQualifiedName("std", "operator<<") } -} - -class ExtractionOperator extends InExOperator { - ExtractionOperator() { hasQualifiedName("std", "operator>>") } + override Expr getFStream() { + result = this.getQualifier() + or + result = this.getArgument(0) and this.getNumberOfArguments() = 2 + } } -/** - * A call to a `FileStream` insertion or extractor operator. - */ -class InExOperatorCall extends FileStreamFunctionCall { - InExOperatorCall() { getTarget() instanceof InExOperator } +class ExtractionOperatorCall extends FileStreamFunctionCall { + ExtractionOperatorCall() { this.getTarget().(Operator).hasQualifiedName("std", "operator>>") } - /** - * Get the `FileStream` expression on which the operator is called. - */ override Expr getFStream() { - result = getQualifier() + result = this.getQualifier() or - result = getArgument(0) and getNumberOfArguments() = 2 + result = this.getArgument(0) and this.getNumberOfArguments() = 2 } } @@ -83,19 +85,26 @@ class OpenFunctionCall extends FileStreamFunctionCall { * A call to `close` functions. */ class CloseFunctionCall extends FileStreamFunctionCall { - CloseFunctionCall() { getTarget().hasQualifiedName("std", "basic_fstream", "close") } + CloseFunctionCall() { + this.getTarget().hasQualifiedName("std", "basic_fstream", "close") or + this.getTarget().hasGlobalName("fclose") + } - override Expr getFStream() { result = getQualifier() } + override Expr getFStream() { + result = getQualifier() + or + result = this.getArgument(0) and this.getNumberOfArguments() = 1 + } } /** - * A call to `seekg` or `seekp` functions. + * A call to `std:basic_istream:seekg`, `std:basic_istream:seekg`, + * `fflush`,`fseek`,`fsetpos`,`rewind` functions. */ -class SeekFunctionCall extends FileStreamFunctionCall { - SeekFunctionCall() { - getTarget().hasQualifiedName("std", "basic_istream", "seekg") - or - getTarget().hasQualifiedName("std", "basic_ostream", "seekp") +class FileStreamPositioningCall extends FileStreamFunctionCall { + FileStreamPositioningCall() { + this.getTarget().hasQualifiedName("std", "basic_istream", "seekg") or + this.getTarget().hasQualifiedName("std", "basic_ostream", "seekp") } override Expr getFStream() { result = getQualifier() } @@ -106,9 +115,9 @@ class SeekFunctionCall extends FileStreamFunctionCall { */ class IOStreamFunctionCall extends FileStreamFunctionCall { IOStreamFunctionCall() { - getTarget().getDeclaringType() instanceof IStream + this.getTarget().getDeclaringType() instanceof IStream or - getTarget().getDeclaringType() instanceof OStream + this.getTarget().getDeclaringType() instanceof OStream } override Expr getFStream() { @@ -140,6 +149,18 @@ class FileStreamConstructorCall extends FileStreamSource, Expr { } } +/** + * A `FileStream` defined externally, and which therefore cannot be tracked as a source by taint tracking. + */ +class FileStreamExternGlobal extends FileStreamSource, GlobalOrNamespaceVariable { + FileStreamExternGlobal() { this.getType().stripType() instanceof FileStream } + + override Expr getAUse() { + // Defined externally, so assume any access is a use. + result = getAnAccess() + } +} + /** * A global taint tracking configuration to track `FileStream` uses in the program. */ @@ -165,15 +186,3 @@ private class FileStreamConstructorCallUseConfig extends TaintTracking::Configur ) } } - -/** - * A `FileStream` defined externally, and which therefore cannot be tracked as a source by taint tracking. - */ -class FileStreamExternGlobal extends FileStreamSource, GlobalOrNamespaceVariable { - FileStreamExternGlobal() { getType().stripType() instanceof FileStream } - - override Expr getAUse() { - // Defined externally, so assume any access is a use. - result = getAnAccess() - } -} diff --git a/cpp/common/src/qlpack.yml b/cpp/common/src/qlpack.yml index 0bdf811d3e..f1a0147457 100644 --- a/cpp/common/src/qlpack.yml +++ b/cpp/common/src/qlpack.yml @@ -1,3 +1,3 @@ name: common-cpp-coding-standards -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: codeql-cpp diff --git a/cpp/common/test/deviations/deviation_permits_basic_test/TypeLongDoubleUsed.ql b/cpp/common/test/deviations/deviation_permits_basic_test/TypeLongDoubleUsed.ql index f9fe6f360a..0ff7b93251 100644 --- a/cpp/common/test/deviations/deviation_permits_basic_test/TypeLongDoubleUsed.ql +++ b/cpp/common/test/deviations/deviation_permits_basic_test/TypeLongDoubleUsed.ql @@ -16,6 +16,7 @@ import cpp import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.cpp.RuleMetadata predicate isUsingLongDouble(ClassTemplateInstantiation c) { c.getATemplateArgument() instanceof LongDoubleType or diff --git a/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql b/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql index fe4370a5ee..38b75bda3c 100644 --- a/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviation_permits_basic_test/UnusedReturnValue.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.CodingStandards import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ /* diff --git a/cpp/common/test/deviations/deviation_permits_basic_test/UselessAssignment.ql b/cpp/common/test/deviations/deviation_permits_basic_test/UselessAssignment.ql index 12e4156f42..a678a1a27e 100644 --- a/cpp/common/test/deviations/deviation_permits_basic_test/UselessAssignment.ql +++ b/cpp/common/test/deviations/deviation_permits_basic_test/UselessAssignment.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.CodingStandards import codingstandards.cpp.deadcode.UselessAssignments +import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ from SsaDefinition ultimateDef, InterestingStackVariable v diff --git a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.ql b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.ql index f9fe6f360a..0ff7b93251 100644 --- a/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.ql +++ b/cpp/common/test/deviations/deviations_basic_test/TypeLongDoubleUsed.ql @@ -16,6 +16,7 @@ import cpp import codingstandards.cpp.CodingStandards +import codingstandards.cpp.exclusions.cpp.RuleMetadata predicate isUsingLongDouble(ClassTemplateInstantiation c) { c.getATemplateArgument() instanceof LongDoubleType or diff --git a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql index fe4370a5ee..38b75bda3c 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviations_basic_test/UnusedReturnValue.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.CodingStandards import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ /* diff --git a/cpp/common/test/deviations/deviations_basic_test/UselessAssignment.ql b/cpp/common/test/deviations/deviations_basic_test/UselessAssignment.ql index 12e4156f42..a678a1a27e 100644 --- a/cpp/common/test/deviations/deviations_basic_test/UselessAssignment.ql +++ b/cpp/common/test/deviations/deviations_basic_test/UselessAssignment.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.CodingStandards import codingstandards.cpp.deadcode.UselessAssignments +import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ from SsaDefinition ultimateDef, InterestingStackVariable v diff --git a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql index fe4370a5ee..38b75bda3c 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql +++ b/cpp/common/test/deviations/deviations_report_deviated/UnusedReturnValue.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.CodingStandards import semmle.code.cpp.dataflow.DataFlow +import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ /* diff --git a/cpp/common/test/deviations/deviations_report_deviated/UselessAssignment.ql b/cpp/common/test/deviations/deviations_report_deviated/UselessAssignment.ql index 12e4156f42..a678a1a27e 100644 --- a/cpp/common/test/deviations/deviations_report_deviated/UselessAssignment.ql +++ b/cpp/common/test/deviations/deviations_report_deviated/UselessAssignment.ql @@ -17,6 +17,7 @@ import cpp import codingstandards.cpp.CodingStandards import codingstandards.cpp.deadcode.UselessAssignments +import codingstandards.cpp.exclusions.cpp.RuleMetadata /* This is a copy of an AUTOSAR rule, which we are using for testing purposes. */ from SsaDefinition ultimateDef, InterestingStackVariable v diff --git a/cpp/common/test/qlpack.yml b/cpp/common/test/qlpack.yml index a9a0e4860e..5aa8100a6f 100644 --- a/cpp/common/test/qlpack.yml +++ b/cpp/common/test/qlpack.yml @@ -1,4 +1,4 @@ name: common-cpp-coding-standards-tests -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: common-cpp-coding-standards extractor: cpp diff --git a/cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.expected b/cpp/common/test/rules/hashoperatorsused/HashOperatorsUsed.expected similarity index 100% rename from cpp/autosar/test/rules/M16-3-2/HashOperatorsShouldNotBeUsed.expected rename to cpp/common/test/rules/hashoperatorsused/HashOperatorsUsed.expected diff --git a/cpp/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql b/cpp/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql new file mode 100644 index 0000000000..d0ead0b289 --- /dev/null +++ b/cpp/common/test/rules/hashoperatorsused/HashOperatorsUsed.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.hashoperatorsused.HashOperatorsUsed diff --git a/cpp/common/test/rules/hashoperatorsused/test.cpp b/cpp/common/test/rules/hashoperatorsused/test.cpp new file mode 100644 index 0000000000..422bde164c --- /dev/null +++ b/cpp/common/test/rules/hashoperatorsused/test.cpp @@ -0,0 +1,19 @@ +#define MACROONE 1 // COMPLIANT + +#define MACROTWO '#' // COMPLIANT + +#define MACROTHREE "##" // COMPLIANT + +#define MACROFOUR "##" + "#" // COMPLIANT + +#define MACROFIVE(X) #X // NON_COMPLIANT + +#define MACROSIX(X, Y) X##Y // NON_COMPLIANT + +#define MACROSEVEN "##'" #"#" // NON_COMPLIANT + +#define MACROEIGHT '##' #"#" // NON_COMPLIANT + +#define MACRONINE "##\"\"" + "#" // COMPLIANT + +#define MACROTEN "##\"\"'" + "#" // COMPLIANT \ No newline at end of file diff --git a/cpp/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected b/cpp/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected index d9f2cf7331..d5afdf5e5a 100644 --- a/cpp/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected +++ b/cpp/common/test/rules/iofstreammissingpositioning/IOFstreamMissingPositioning.expected @@ -1,9 +1,9 @@ -| test.cpp:9:11:9:11 | call to operator<< | Missing call to positioning function before $@. | test.cpp:10:11:10:11 | call to operator>> | call to operator>> | -| test.cpp:10:11:10:11 | call to operator>> | Missing call to positioning function before $@. | test.cpp:11:11:11:11 | call to operator<< | call to operator<< | -| test.cpp:18:11:18:11 | call to operator<< | Missing call to positioning function before $@. | test.cpp:19:11:19:11 | call to operator>> | call to operator>> | -| test.cpp:29:8:29:8 | call to operator>> | Missing call to positioning function before $@. | test.cpp:31:8:31:8 | call to operator<< | call to operator<< | -| test.cpp:40:6:40:6 | call to operator<< | Missing call to positioning function before $@. | test.cpp:41:12:41:12 | call to operator>> | call to operator>> | -| test.cpp:41:12:41:12 | call to operator>> | Missing call to positioning function before $@. | test.cpp:42:6:42:6 | call to operator<< | call to operator<< | -| test.cpp:51:14:51:14 | call to operator>> | Missing call to positioning function before $@. | test.cpp:52:14:52:14 | call to operator<< | call to operator<< | -| test.cpp:62:12:62:12 | call to operator>> | Missing call to positioning function before $@. | test.cpp:63:12:63:12 | call to operator<< | call to operator<< | -| test.cpp:99:12:99:12 | call to operator>> | Missing call to positioning function before $@. | test.cpp:103:12:103:12 | call to operator<< | call to operator<< | +| test.cpp:10:11:10:11 | call to operator>> | Missing call to positioning function before $@. | test.cpp:9:11:9:11 | call to operator<< | call to operator>> | +| test.cpp:11:11:11:11 | call to operator<< | Missing call to positioning function before $@. | test.cpp:10:11:10:11 | call to operator>> | call to operator<< | +| test.cpp:19:11:19:11 | call to operator>> | Missing call to positioning function before $@. | test.cpp:18:11:18:11 | call to operator<< | call to operator>> | +| test.cpp:31:8:31:8 | call to operator<< | Missing call to positioning function before $@. | test.cpp:29:8:29:8 | call to operator>> | call to operator<< | +| test.cpp:41:12:41:12 | call to operator>> | Missing call to positioning function before $@. | test.cpp:40:6:40:6 | call to operator<< | call to operator>> | +| test.cpp:42:6:42:6 | call to operator<< | Missing call to positioning function before $@. | test.cpp:41:12:41:12 | call to operator>> | call to operator<< | +| test.cpp:52:14:52:14 | call to operator<< | Missing call to positioning function before $@. | test.cpp:51:14:51:14 | call to operator>> | call to operator<< | +| test.cpp:63:12:63:12 | call to operator<< | Missing call to positioning function before $@. | test.cpp:62:12:62:12 | call to operator>> | call to operator<< | +| test.cpp:103:12:103:12 | call to operator<< | Missing call to positioning function before $@. | test.cpp:99:12:99:12 | call to operator>> | call to operator<< | diff --git a/cpp/common/test/rules/nonconstantformat/NonConstantFormat.expected b/cpp/common/test/rules/nonconstantformat/NonConstantFormat.expected new file mode 100644 index 0000000000..bb0bcaa558 --- /dev/null +++ b/cpp/common/test/rules/nonconstantformat/NonConstantFormat.expected @@ -0,0 +1 @@ +| test.cpp:11:19:11:21 | msg | The format string argument to `$@` should be constant to prevent security issues and other potential errors. | test.cpp:11:3:11:9 | call to fprintf | fprintf | diff --git a/cpp/common/test/rules/nonconstantformat/NonConstantFormat.ql b/cpp/common/test/rules/nonconstantformat/NonConstantFormat.ql new file mode 100644 index 0000000000..7a92b544e2 --- /dev/null +++ b/cpp/common/test/rules/nonconstantformat/NonConstantFormat.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.nonconstantformat.NonConstantFormat diff --git a/cpp/autosar/test/rules/A27-0-1/test.cpp b/cpp/common/test/rules/nonconstantformat/test.cpp similarity index 99% rename from cpp/autosar/test/rules/A27-0-1/test.cpp rename to cpp/common/test/rules/nonconstantformat/test.cpp index 6165ec3a42..857075cccf 100644 --- a/cpp/autosar/test/rules/A27-0-1/test.cpp +++ b/cpp/common/test/rules/nonconstantformat/test.cpp @@ -17,4 +17,4 @@ void F2(const char *input) { } void F3(const std::string &input) { std::cerr << "IN: " << input; // COMPLIANT -} \ No newline at end of file +} diff --git a/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected b/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected index eb7b1754fa..d5d138ec19 100644 --- a/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected +++ b/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected @@ -6,36 +6,18 @@ problems | test.cpp:12:28:12:29 | v2 | test.cpp:10:8:10:17 | new | test.cpp:12:28:12:29 | v2 | Raw pointer flows to initialize multiple unrelated smart pointers. | | test.cpp:17:27:17:28 | v1 | test.cpp:16:13:16:22 | new | test.cpp:17:27:17:28 | v1 | Raw pointer flows to initialize multiple unrelated smart pointers. | edges -| ../../includes/standard-library/memory.h:76:17:76:19 | ptr | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | | test.cpp:3:14:3:15 | v1 | test.cpp:5:27:5:28 | v1 | | test.cpp:3:14:3:15 | v1 | test.cpp:6:31:6:33 | call to get | | test.cpp:3:14:3:15 | v1 | test.cpp:7:28:7:29 | v2 | | test.cpp:4:13:4:14 | v1 | test.cpp:7:28:7:29 | v2 | -| test.cpp:5:27:5:28 | v1 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | | test.cpp:5:27:5:29 | call to shared_ptr | test.cpp:6:31:6:33 | call to get | -| test.cpp:6:31:6:33 | call to get | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:6:31:6:33 | call to get | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:7:28:7:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:7:28:7:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | | test.cpp:8:8:8:14 | 0 | test.cpp:9:28:9:29 | v2 | -| test.cpp:9:28:9:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:10:8:10:17 | new | test.cpp:11:28:11:29 | v2 | | test.cpp:10:8:10:17 | new | test.cpp:11:28:11:29 | v2 | | test.cpp:10:8:10:17 | new | test.cpp:12:28:12:29 | v2 | -| test.cpp:11:28:11:29 | ref arg v2 | test.cpp:12:28:12:29 | v2 | -| test.cpp:11:28:11:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:11:28:11:29 | v2 | test.cpp:11:28:11:29 | ref arg v2 | -| test.cpp:12:28:12:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:16:13:16:22 | new | test.cpp:17:27:17:28 | v1 | | test.cpp:16:13:16:22 | new | test.cpp:17:27:17:28 | v1 | | test.cpp:16:13:16:22 | new | test.cpp:19:6:19:7 | v1 | -| test.cpp:17:27:17:28 | ref arg v1 | test.cpp:19:6:19:7 | v1 | -| test.cpp:17:27:17:28 | v1 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:17:27:17:28 | v1 | test.cpp:17:27:17:28 | ref arg v1 | | test.cpp:19:6:19:7 | v1 | test.cpp:3:14:3:15 | v1 | nodes -| ../../includes/standard-library/memory.h:76:17:76:19 | ptr | semmle.label | ptr | -| ../../includes/standard-library/memory.h:76:17:76:19 | ptr | semmle.label | ptr | | test.cpp:3:14:3:15 | v1 | semmle.label | v1 | | test.cpp:4:13:4:14 | v1 | semmle.label | v1 | | test.cpp:5:27:5:28 | v1 | semmle.label | v1 | @@ -45,15 +27,9 @@ nodes | test.cpp:8:8:8:14 | 0 | semmle.label | 0 | | test.cpp:9:28:9:29 | v2 | semmle.label | v2 | | test.cpp:10:8:10:17 | new | semmle.label | new | -| test.cpp:11:28:11:29 | ref arg v2 | semmle.label | ref arg v2 | -| test.cpp:11:28:11:29 | v2 | semmle.label | v2 | | test.cpp:11:28:11:29 | v2 | semmle.label | v2 | | test.cpp:12:28:12:29 | v2 | semmle.label | v2 | | test.cpp:16:13:16:22 | new | semmle.label | new | -| test.cpp:17:27:17:28 | ref arg v1 | semmle.label | ref arg v1 | -| test.cpp:17:27:17:28 | v1 | semmle.label | v1 | | test.cpp:17:27:17:28 | v1 | semmle.label | v1 | | test.cpp:19:6:19:7 | v1 | semmle.label | v1 | subpaths -| test.cpp:11:28:11:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | test.cpp:11:28:11:29 | ref arg v2 | -| test.cpp:17:27:17:28 | v1 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | test.cpp:17:27:17:28 | ref arg v1 | \ No newline at end of file diff --git a/cpp/autosar/test/rules/A16-2-1/'badheader.h b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/'badheader.h similarity index 100% rename from cpp/autosar/test/rules/A16-2-1/'badheader.h rename to cpp/common/test/rules/preprocessorincludesforbiddenheadernames/'badheader.h diff --git a/cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.expected b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.expected similarity index 100% rename from cpp/autosar/test/rules/A16-2-1/CharactersOccurInHeaderFileNameOrInIncludeDirective.expected rename to cpp/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.expected diff --git a/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql new file mode 100644 index 0000000000..1b27d1e0ee --- /dev/null +++ b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/PreprocessorIncludesForbiddenHeaderNames.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.preprocessorincludesforbiddenheadernames.PreprocessorIncludesForbiddenHeaderNames diff --git a/cpp/autosar/test/rules/A16-2-1/badheade'r.h b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/badheade'r.h similarity index 100% rename from cpp/autosar/test/rules/A16-2-1/badheade'r.h rename to cpp/common/test/rules/preprocessorincludesforbiddenheadernames/badheade'r.h diff --git a/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/test.cpp b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/test.cpp new file mode 100644 index 0000000000..1d730c5caf --- /dev/null +++ b/cpp/common/test/rules/preprocessorincludesforbiddenheadernames/test.cpp @@ -0,0 +1,14 @@ +#include "./string.h" //COMPLIANT +#include "string.h" //COMPLIANT + +#include "'badheader.h" //NON_COMPLIANT +#include "badheade'r.h" //NON_COMPLIANT + +// cannot use this filename in Windows +//#include "*.h" //NON_COMPLIANT + +// cannot use this filename in Windows +//#include "\\badheader.h" //NON_COMPLIANT + +//#include <"badheader.h"> //NON_COMPLIANT[FALSE_NEGATIVE] +//#include //NON_COMPLIANT[FALSE_NEGATIVE] \ No newline at end of file diff --git a/cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.expected b/cpp/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.expected similarity index 100% rename from cpp/autosar/test/rules/M16-0-1/IncludeDirectivesNotPrecededByDirectivesOrComments.expected rename to cpp/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.expected diff --git a/cpp/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql b/cpp/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql new file mode 100644 index 0000000000..343b168637 --- /dev/null +++ b/cpp/common/test/rules/preprocessorincludespreceded/PreprocessorIncludesPreceded.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.preprocessorincludespreceded.PreprocessorIncludesPreceded diff --git a/cpp/autosar/test/rules/M16-0-1/test.cpp b/cpp/common/test/rules/preprocessorincludespreceded/test.cpp similarity index 100% rename from cpp/autosar/test/rules/M16-0-1/test.cpp rename to cpp/common/test/rules/preprocessorincludespreceded/test.cpp diff --git a/cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.expected b/cpp/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.expected similarity index 100% rename from cpp/autosar/test/rules/M16-0-7/UndefinedMacroIdentifiersUsedIn.expected rename to cpp/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.expected diff --git a/cpp/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql b/cpp/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql new file mode 100644 index 0000000000..afede1b8ef --- /dev/null +++ b/cpp/common/test/rules/undefinedmacroidentifiers/UndefinedMacroIdentifiers.ql @@ -0,0 +1,2 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.cpp.rules.undefinedmacroidentifiers.UndefinedMacroIdentifiers diff --git a/cpp/autosar/test/rules/M16-0-7/test.cpp b/cpp/common/test/rules/undefinedmacroidentifiers/test.cpp similarity index 100% rename from cpp/autosar/test/rules/M16-0-7/test.cpp rename to cpp/common/test/rules/undefinedmacroidentifiers/test.cpp diff --git a/cpp/misra/src/qlpack.yml b/cpp/misra/src/qlpack.yml index 8583578e30..5e928d0fc6 100644 --- a/cpp/misra/src/qlpack.yml +++ b/cpp/misra/src/qlpack.yml @@ -1,3 +1,3 @@ name: misra-cpp-coding-standards -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: common-cpp-coding-standards diff --git a/cpp/misra/test/qlpack.yml b/cpp/misra/test/qlpack.yml index a4f0fb3317..295923be97 100644 --- a/cpp/misra/test/qlpack.yml +++ b/cpp/misra/test/qlpack.yml @@ -1,4 +1,4 @@ name: misra-cpp-coding-standards-tests -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: misra-cpp-coding-standards extractor: cpp diff --git a/cpp/report/src/qlpack.yml b/cpp/report/src/qlpack.yml index 3f991a6414..ed6297483e 100644 --- a/cpp/report/src/qlpack.yml +++ b/cpp/report/src/qlpack.yml @@ -1,3 +1,3 @@ name: report-cpp-coding-standards -version: 1.1.0 +version: 2.0.0 libraryPathDependencies: codeql-cpp diff --git a/docs/development_handbook.md b/development_handbook.md similarity index 65% rename from docs/development_handbook.md rename to development_handbook.md index 58805cf6f8..acc2da6f03 100644 --- a/docs/development_handbook.md +++ b/development_handbook.md @@ -1,46 +1,21 @@ # Coding Standards: Developer handbook -## Document management - -**Document ID:** codeql-coding-standards/developer-handbook - -| Version | Date | Author | Changes | -| ------- | ---------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 0.1.0 | 2021-02-02 | Luke Cartey | Initial version. | -| 0.2.0 | 2021-02-19 | Luke Cartey | Add section on Python environment preparation. | -| 0.3.0 | 2021-04-13 | Michael Hohn | Add cookbook section documenting common procedures. | -| 0.4.0 | 2021-04-13 | Mario Campos | Add submodule out of date tip to the cookbook section. | -| 0.5.0 | 2021-04-30 | Luke Cartey | Add query style guide. | -| 0.6.0 | 2021-05-05 | John Singleton | Add task automation files. | -| 0.7.0 | 2021-05-10 | Luke Cartey | Explain non-constant alert messages. | -| 0.8.0 | 2021-05-27 | Luke Cartey | Clarify the `short_name` property. | -| 0.9.0 | 2021-09-06 | Luke Cartey |
    • Update code review requirements.
    • Update release process documentation.
    | -| 0.10.0 | 2021-09-08 | Luke Cartey | Update tool qualification section. | -| 0.11.0 | 2021-09-10 | Luke Cartey | Add reporting and deviations to scope of work. | -| 0.12.0 | 2021-09-18 | Luke Cartey |
    • Document conditions for overriding PR checks.
    • Clarify that LGTM and GHAS are out of scope.
    • Document our used versioning control system.
    | -| 0.13.0 | 2021-09-22 | Remco Vermeulen | Document rule package schema. | -| 0.14.0 | 2021-10-11 | Luke Cartey | Document how to update dependencies. | -| 0.15.0 | 2021-10-26 | John Singleton | Document false positive triage process. | -| 0.16.0 | 2021-11-29 | Remco Vermeulen | Add document management section. | -| 0.17.0 | 2021-11-29 | Remco Vermeulen |
    • Explain the process of determining if a guideline is amenable to automated static analysis.
    • Document the supported language.
    • Document the `short_name` property update process.
    • Describe guidelines for splitting a rule into multiple queries.
    | -| 0.18.0 | 2022-02-16 | Remco Vermeulen | Address mistake in point 2 in section *Splitting a rule into multiple queries*. | - ## Scope of work A _coding standard_ is a set of rules or guidelines which restrict or prohibit the use of certain dangerous or confusing coding patterns or language features. This repository contains CodeQL queries (and supporting processes) which implement a number of different coding standards. The currently supported standards are: -| Standard | Version | Total rules | Total supportable rules | Status | Notes | -| -------------------------------------------------------------------------------------------------------------------- | ------- | ----------- | ----------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [AUTOSAR C++](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/20-11/AUTOSAR_RS_CPP14Guidelines.pdf) | 20-11 | 397 | 375 | Implemented | -| [CERT-C++](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf) | 2016 | 83 | 83 | Implemented | AUTOSAR includes a sub-set of rules take from MISRA C++ 2008, which can be purchased for a small fee from [the MISRA website](https://misra.org.uk/shop). | +| Standard | Version | Total rules | Total supportable rules | Status | Notes | +| -------------------------------------------------------------------------------------------------------------------- | ------- | ----------- | ----------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [AUTOSAR C++](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/20-11/AUTOSAR_RS_CPP14Guidelines.pdf) | 20-11 | 397 | 375 | In development | +| [CERT-C++](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf) | 2016 | 83 | 83 | In development | AUTOSAR includes a sub-set of rules take from MISRA C++ 2008, which can be purchased for a small fee from [the MISRA website](https://misra.org.uk/shop). | -Each coding standard consists of a list of "guidelines", however not all the guidelines in all the standards will be amenable to automated static analysis. The AUTOSAR C++ standard categorizes the guidelines according to enforcement by static analysis tools in section _5.1.3 Rule classification according to enforcement by static analysis_ of the standard. The CERT-C++ standard does not provide such categorization, but frequently has a [documented](https://wiki.sei.cmu.edu/confluence/display/cplusplus/How+this+Coding+Standard+Is+Organized#HowthisCodingStandardIsOrganized-AutomatedDetection) automated detection section for guidelines that documents tools, including their limitations, that can verify the guidelines in question. We have therefore carefully reviewed each supported standard. For each guidelines that is not categorized as automatic enforceable we have determined,in conjunction with end users, what parts of the guideline can be supported in which capacity with CodeQL. +Each coding standard consists of a list of "rules", however not all the rules in all the standards will be amenable to automated static analysis. We have therefore carefully reviewed each supported standard, in conjunction with end users, to determine which rules we will write queries for. For some of the rules which are not amenable to static analysis, we may opt to provide a query which aids with "auditing" the rules. For example, AUTOSAR includes a rule (A10-0-1) "Public inheritance shall be used to implement 'is-a' relationship.". This is not directly amenable to static analysis, because it requires external context around the concept being modeled. However, we can provide an "audit" rule which reports all the public and private inheritance relationships in the program, so they can be manually verified. -For each rule which will be implemented with a query we have assigned a "rule package". Rule packages represent sets of rules, possibly across standards, that will be implemented together. Examples of rule packages include "Exceptions", "Naming", "Pointers" and so forth. By implementing queries for related rules together, we intend to maximize the amount of code shared between queries, and to ensure query developers can gain a deep understanding of that specific topic. +For each rule which will be implemented with a query we have assigned a "rule package". Rule packages represent sets of rules, possibly across standards, that will be implemented together. Examples of rule packages include "Exceptions", "Naming", "Pointers" and so forth. By implementing queries for related rules together, we intend to maximise the amount of code shared between queries, and to ensure query developers can gain a deep understanding of that specific topic. -The canonical list of rules, with implementation categorization and assigned rule packages, are stored in this repository in the `rules.csv` file. +The canonical list of rules, with implementation categorisation and assigned rule packages, are stored in this repository in the `rules.csv` file. ### Software tool qualification under ISO 26262 @@ -48,7 +23,7 @@ A common use case for the coding standards specified above is to to help in the To support the functional safety use case, the scope of work for this project also includes: - - _Analysis reporting_ - producing reports for functional safety purposes that summarize the findings and highlight any issues during analysis that could compromise the integrity of those findings. + - _Analysis reporting_ - producing reports for functional safety purposes that summarise the findings and highlight any issues during analysis that could compromise the integrity of those findings. - _Deviations_ - a process for suppressing valid results, and maintaining metadata The requirements for these additional components are taken from the [MISRA Compliance 2020](https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf) document. Further details of these use cases can be found in the [user manual](docs/user_manual.md). @@ -57,7 +32,7 @@ The requirements for these additional components are taken from the [MISRA Compl ### Overview - * For each selected rule we will write one or more CodeQL queries that implement the rule (see section _Splitting a rule into multiple queries_). + * For each selected rule we will write one or more CodeQL queries that implement the rule. * Queries will be grouped into CodeQL packs, according to the coding standard the rule comes from. * To ensure consistency and increase the speed of development, we generate outline query files from the `rules.csv` specification file. * Where a rule is duplicated across different standards, we will still create separate queries for each standard, but the implementation may be shared between the standards. This allows each version to provide different metadata, and to be enabled/disabled individually. @@ -68,9 +43,7 @@ For each supported coding standard we will provide: 1. A CodeQL query pack containing the queries that implement the designated rules. 2. A CodeQL query pack containing the unit tests ("qltests") for each of the queries. -These packs will be organized by supported language. -The current supported language is C++14 standardized by [ISO/IEC 14882:2014](https://www.iso.org/standard/64029.html) and -is located in the directory `cpp`. +These packs will be organised by supported language (e.g. `cpp`, `java` etc.). For each language, we will also include: 1. A CodeQL query pack containing "common" libraries, which provide support. @@ -78,7 +51,7 @@ For each language, we will also include: The standards packs will depend on the "common" pack for the given language. This will allow the different standards to share implementation libraries. -In the repository, this will be organized as follows: +In the repository, this will be organised as follows: ``` / / @@ -111,17 +84,6 @@ In the repository, this will be organized as follows: qlpack.yml ``` -### Splitting a rule into multiple queries - -A coding standard rule can be implemented by multiple CodeQL queries. -The decision to split a rule into multiple queries should be driven by the following guidelines: - -1. A split of a rule in a query simplifies the implementation of each individual query. Indicators are: - - The number of cases with CodeQL classes that cannot be further generalized because they don't have a common ancestor CodeQL class or have conceptually different representations such as local and global declarations. - - Multiple language constructs that must be considered such as template vs non-template classes/functions. -2. A corner case of a rule that is responsible for a significant number of alerts in projects not build with that case in mind. A separate query enables a sub-rule deviation. - - An example is the Autosar guideline `A2-3-1` that prohibits the use of characters outside the basic source character set defined in `[lex.charset]`. Having a separate rule for comments enables a deviation on violations in just comments and keeps violations detected in string literals or identifiers. - ### Generation of query templates from rule specifications In order to speed up rule development and ensure implementation consistency we have created a series of scripts that generate templated rule files based on the `rules.csv` rule specification file. This generation process works on a per-rule package basis, and is driven by the creation of a "rule package description file", describing the mapping from rules to queries which will implement those rules. @@ -131,17 +93,9 @@ For this, there is a three step process: 2. Review each entry in the rule package description file, updating the names and properties of the queries that will be written to implement these rules. 3. Generate rule files from the rule package description file for a given rule package. -After these scripts have been run each query specified in the rule package description file will have: - -- query files, -- query help files, -- empty query test files, and -- query test reference files generated in per-rule directories within each coding standard. - -These files will be ready for query implementation. +After these scripts have been run each query specified in the rule package description file will have query files, query help files, empty query test files and query test reference files generated in per-rule directories within each coding standard. These files will be ready for query implementation. #### Step 0: Prepare the Python environment - The `scripts` directory contains the pip package specification file `requirements.txt` that contains the dependencies our generation scripts rely upon. The dependencies can be installed as follows: @@ -216,11 +170,7 @@ For example, this is the first part of the `Exceptions2.json` package file: } ``` -The `generate_package_description.py` script generates a rule package description file which has a single query per-rule and each query is described by a set of properties. -The properties of a query include the [documented](https://codeql.github.com/docs/writing-codeql-queries/metadata-for-codeql-queries/#metadata-properties) metadata properties of a CodeQL query and a name used, defined by the `short_name` property, to generate the required query files. -The query metadata instructs the CodeQL how to handle the query and display its results. It also provides the users with information about what the query results mean. - -The `generate_package_description.py` script provides a "best-effort" approach to setting each of the properties. For that reason, the rule package description file must be reviewed and updated. For each rule: +The `generate_package_description.py` script generates a rule package description file which has a single query per-rule, and provides a "best-effort" approach to setting each of the properties. For that reason, the rule package description file must be reviewed and updated. For each rule: - Review the rule text in the relevant standard, and determine the number of queries - For each `query` object review and update the following properties: @@ -234,7 +184,7 @@ The `generate_package_description.py` script provides a "best-effort" approach t - `recommendation` - if the reported issue is primarily a stylistic or maintainability issue. - `short_name` - must be a PascalCase string without spaces, which will be used for the name of the query file and to generate a query id. Pre-populated heuristically from from the rule headline text. Make adjustments as appropriate: - The short name must not exceed 50 characters. - - Consider whether the query can be described more succinctly. For example `OnlyInstancesOfTypesDerivedFromExceptionShouldBeThrown` can be summarized more clearly as `OnlyThrowStdExceptionDerivedTypes`. + - Consider whether the query can be described more succinctly. For example `OnlyInstancesOfTypesDerivedFromExceptionShouldBeThrown` can be summarised more clearly as `OnlyThrowStdExceptionDerivedTypes`. - `tags` - Apply at least one tag from the possible values listed below. If you want to use a query that is not listed a new tag can be added through a PR that modifies the possible tag values in the `query` sub-schema located in `schemas/rule-package.schema.json` and updates the list of possible values described below. - `correctness` - if the query identifies incorrect program behavior. - `security` - if the query identifies a potential security vulnerability. @@ -246,7 +196,6 @@ The `generate_package_description.py` script provides a "best-effort" approach t - `python3 scripts/validate-rule-package.py ` #### Step 3: - To generate the rule package files, run the following script from the root of the repository: ``` @@ -272,36 +221,9 @@ The notable exceptions are: - If a `query` object is deleted from the rule package description file, it will not be deleted on disk. - If a `query` object has the `short_name` property modified in the rule package description file, query files will be created under the new name, but the query files for the old name will not be deleted. -### Updating the query from the rule specification - -Updates to the rule specification require an update of the generated queries files. -As described in _step 3_ of the section _Generation of query templates from rule specifications_ the script `scripts/generate_rules/generate_package_files.py` can be safely re-run with the documented exceptions. - -Each property of a query in the rule specification can be changed and the generated query files can be updated by rerunning the script `scripts/generate_rules/generate_package_files.py` with exception of the property `query.shortname`. Updating the `query.shortname` property is discussed in the next section. - -#### Updating the query shortname - -Changing the `query.shortname` property requires a manual update process with the following steps. - -1. Determine the query who's `query.shortname` property needs to be updated. -2. Change the `query.shortname` value and generate the query files as described in _step 3_ of the section _Generation of query templates from rule specifications_. -3. Migrate the query definition (excluding the query meta-data) from the previous query file to the new query file identified with the updated shortname. -4. Migrate the test case expected file identified by old `.expected` to the update `.expected` name. -5. Validate that the new test case passes by following the procedure described in the section _Running unit tests_. -6. Remove the following files with `git rm ` where `query.shortname` reflects the old shortname in the directory `//src/rules//`: - - `.ql` - - `.qhelp` - - `-implementation.qhelp` -7. Remove the following files with `git rm ` where `query.shortname` reflects the old shortname in the directory `//test/rules//`: - - `.qlref` - - `.qhelp` - - `.expected` - ### Query style guide -The following list describes the required style guides for a query that **must** be validated during the code-review process described in section _Code review and automated checks_. - -A query **must** include: +A query should include: - A use of the `isExcluded` predicate on the element reported as the primary location. This predicate ensures that we have a central mechanism for excluding results. This predicate may also be used on other elements relevant to the alert, but only if a suppression on that element should also cause alerts on the current element to be suppressed. - A well formatted alert message: - The message should be a complete standalone sentence, with punctuation and a full stop. @@ -317,10 +239,7 @@ All public predicates, classes, modules and files should be documented with QLDo ### Unit testing -Every query which implements a rule **must** include: -- One or more unit tests. -- One or more unit tests for every non-trivial library. -- For each unit test both "compliant" and "non-compliant" test cases, and should exercise each different logical condition uniquely provided in the query, where possible within the testing framework. The scope of each test should be those conditions specific to this query. In particular, functionality provided by the CodeQL Standard Library for C++ does not need to be tested. +Every query which implements a rule _must_ include one or more unit tests. In addition, every non-trivial library should also include one or more unit tests. Each unit test should include both "compliant" and "non-compliant" test cases, and should exercise each different logical condition uniquely provided in the query, where possible within the testing framework. The scope of each test should be those conditions specific to this query. In particular, functionality provided by the CodeQL Standard Library for C++ does not need to be tested. #### Running unit tests @@ -339,7 +258,7 @@ For more details on running unit tests with the CodeQL CLI see the [Testing cust #### Style guide -The C++ test cases **must** be formatted with `clang_format`. +The C++ test cases should be formatted with `clang_format`. - Test functions should be called `test_`, where `` is a brief description of this test case. @@ -350,7 +269,7 @@ If possible, use meaningful names for elements in test cases. Where arbitrary na - Functions should be named `f`, with i incremented for each new variable. - Member variables should be named `m`, with i incremented for each new variable. -Test cases **must** be annotated with a line-ending comment in this format: +Test cases should be annotated with a line-ending comment in this format: ``` (COMPLIANT(\[FALSE_POSITIVE\])?|NON_COMPLIANT(\[FALSE_NEGATIVE\])?)( - .*)? ``` @@ -429,7 +348,7 @@ A _change note_ must be added to the `change_notes` directory. The format of the ``` YYYY-MM-DD-short-name-for-issue.md ``` -For example `2021-06-29-remove-incompatibility-codeql-cli-2.5.6.md`. +For example `2021-06-29-remove-incompatability-codeql-cli-2.5.6.md`. The contents of the file should be a markdown list (using `-`) with a user facing message specifying the nature of the change. If the changes relate to specific queries, then the top-level entry should specify the rule and query, and should provide a nested list of the changes. For example: ``` @@ -490,15 +409,6 @@ To upgrade the CodeQL external dependencies: ### Release process -#### Version Numbering - -Version numbers follow semantic versioning and adhere to the following guidelines specific to Coding Standards. - -Given the version `..`: - -1. If the release only fixes bugs, increment the `PATCH` number only. -2. If a release contains additional queries, increment the `MINOR` version number and set the `PATCH` number to 0. Note this may also contain fixes in addition to new queries. -3. Otherwise, if the release contains breaking changes such as removing queries, increment the `MAJOR` version number and set `MINOR` and `PATCH` to zero. #### Release management We use the "Releases" feature in GitHub to manage and track our releases. This provides traceability back to the specific commit in the repository that was released, a storage location for release artifacts and a location to report the release notes associated with the release. @@ -533,49 +443,48 @@ These run on every push to `main` and `rc/*`, and on every pull request, and are To create a new release: 1. Create an internal "release checklist" issue. - 2. Determine the appropriate release version. Version numbers are generated - according to the guidelines in the section "Version Numbering." - 3. If a new `MAJOR` version is necessary, create a new `rc/.0` branch off of `main`. Otherwise, reuse the existing `rc` branch and merge work from `main` into the `rc` branch you have selected. - 4. Submit a PR to update the `qlpack.yml` version numbers on the `main` branch to the next anticipated release. - 5. Submit a PR to update the `qlpack.yml` version numbers on the release branch to the new version. - 6. Trigger a [workflow dispatch event](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) for the [Create draft release](.github/workflows/create-draft-release.yml) workflow, specifying the release branch. The output of this workflow should report a link to the draft release and a link to the integration testing workflow triggered for this release. + 2. Determine the appropriate release version: + - If this is a patch release (fixing a bug etc.), then identify the previous release and release branch to which the patch applies, and increment the patch number. + - If this is a pre-1.0.0 with support for new rule packages, then then increment the `minor` version from the last release, and create a new branch called `rc/0.`. + - If this is a post 1.0.0 release, then: + - If support for new rules has been added or removed then increment the `major` version from the last release + 3. If the major or minor versions have been incremented, then: + a. Create a new branch for the release with the name `rc/.`, and branched from `main` (where "rc" is release candidate, and `` and `` is replaced with the version numbers identified in Step 2.). + b. Submit a PR to update the `qlpack.yml` version numbers on the `main` branch to the next anticipated release. + 4. Submit a PR to update the `qlpack.yml` version numbers on the release branch to the new version. + 5. Trigger a [workflow dispatch event](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) for the [Create draft release](.github/workflows/create-draft-release.yml) workflow, specifying the release branch. The output of this workflow should report a link to the draft release and a link to the integration testing workflow triggered for this release. - In the event the workflow is unusable, the [`create_draft_release.sh`](scripts/releases/create_draft_release.sh) script can be run directly on a local machine. - 7. Run the following workflows with the new version number, e.g., `v2.0.0`: - - [Test Linux/x86_64](https://github.com/github/codeql-coding-standards-release-engineering/actions/workflows/test-release-performance-linux-x86_64.yml) - - [Test Windows/x86_64](https://github.com/github/codeql-coding-standards-release-engineering/actions/workflows/test-release-performance-windows-x86_64.yml) - - [Regenerate Performance Views](https://github.com/github/codeql-coding-standards-release-engineering/actions/workflows/regenerate-performance-views.yml) - 8. Confirm the integration testing workflow completes successfully, and that the execution time is comparable to previous releases, taking into account that the execution time is expected to increase proportionally as more queries are added for each release. Results may be viewed on the release engineering repo: https://github.com/github/codeql-coding-standards-release-engineering - 9. For release 1.0.0 and above, the integration testing results must be verified. For each "integration testing codebase": + 6. Confirm the integration testing workflow completes successfully, and that the execution time is comparable to previous releases, taking into account that the execution time is expected to increase proportionally as more queries are added for each release. + 7. For release 1.0.0 and above, the integration testing results must be verified. For each "integration testing codebase": - Download the SARIF result file - Compare the results against the previously computed set of results for that integration testing codebase, and, for any new or changed results, spot check to confirm validity. - For false positives and false negatives identified during this process issues should be opened on this repository to track the problems identified. - For each issue opened, assess whether they are "significant" i.e. whether they are likely to cause problems in practice with customers. If so, consider Step 7. failed. - 10. If the release fails steps 6. or 7. (if applicable), retain the draft release, and rename it to `vminor.major.patch-rc`. Address the release blocking issues on the `rc/.` branch, and restart the release process at Step 5. - 11. If steps 6. and 7. (if applicable) succeeded, then the release can be marked as "published". - 12. Release artifacts can now be distributed to customers. - 13. Create an internal "release retrospective" issue, and document any pain points or other issues. - 14. Create a PR that merges the release candidate branch into `main`. - -## False Positive Triage Rubric + 8. If the release fails steps 6. or 7. (if applicable), retain the draft release, and rename it to `vminor.major.patch-rc`. Address the release blocking issues on the `rc/.` branch, and restart the release process at Step 5. + 9. If steps 6. and 7. (if applicable) succeeded, then the release can be marked as "published". + 10. Release artifacts can now be distributed to customers. + 11. Create an internal "release retrospective" issue, and document any pain points or other issues. + 12. Create a PR that merges the release candidate branch into `main`. +## False Positive Triage Rubric When triaging issues in Coding Standards, please refer to the following rubric for making classifications. **Impact** -| Level | Definition | -| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Level | Definition | +|---------------|------------| | Impact-High | Issue occurs in one or more production code bases with high frequency. Issue is considered to be disruptive to customer. **Issues determined to be Impact-High at the end of a triage session should be assigned with 24 hours.** | -| Impact-Medium | Issue occurs in production code bases with relatively low to moderate frequency. Issue may or may not be considered disruptive to customer. | -| Impact-Low | Issue may not occur in production code bases and may require hand crafted examples to surface. If the issue occurs in production code bases it occurs either infrequently or impacts only a few codebases. | +| Impact-Medium | Issue occurs in production code bases with relatively low to moderate frequency. Issue may or may not be considered disruptive to customer. | +| Impact-Low |Issue may not occur in production code bases and may require hand crafted examples to surface. If the issue occurs in production code bases it occurs either infrequently or impacts only a few codebases. | **Difficulty** -| Level | Definition | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Difficulty-High | High difficulty fixes are issues that take the most time. Probable classes of issues include: A) Fixes to the issue are not isolated (i.e., issue may impact other queries due to changes required to library files). B) Issue involves workarounds for missing syntax that may be brittle C) Issue is a workaround for limitations in the CodeQL standard libraries D) Issue is a performance issue. | -| Difficulty-Medium | Medium difficulty fixes are fixes that do not meet the criteria of High or low Difficulty fixes and involve substantial isolated work to a query on dataflow, taint tracking, or control flow issues. Expanding the set of sources for a query, for example, would be considered a medium difficulty query. | -| Difficulty-Low | Low difficulty fixes are of the lowest complexity and involve non-semantic changes to queries such as changing query metadata, updating error messages, and changes to isolated queries requiring little or no changes to the core query. Examples of allowed changes are adding special cases to an abstract class or supporting different forms previously not considered by the query. | -| Difficulty-Needs-Investigation | Difficulty is not known. Issue needs further investigation beyond the triage session to establish a rating. | +| Level | Definition | +|---------------|------------| +| Difficulty-High | High difficulty fixes are issues that take the most time. Probable classes of issues include: A) Fixes to the issue are not isolated (i.e., issue may impact other queries due to changes required to library files). B) Issue involves workarounds for missing syntax that may be brittle C) Issue is a workaround for limitations in the CodeQL standard libraries D) Issue is a performance issue. | +| Difficulty-Medium | Medium difficulty fixes are fixes that do not meet the criteria of High or low Difficulty fixes and involve substantial isolated work to a query on dataflow, taint tracking, or control flow issues. Expanding the set of sources for a query, for example, would be considered a medium difficulty query. | +| Difficulty-Low | Low difficulty fixes are of the lowest complexity and involve non-semantic changes to queries such as changing query metadata, updating error messages, and changes to isolated queries requiring little or no changes to the core query. Examples of allowed changes are adding special cases to an abstract class or supporting different forms previously not considered by the query. | +| Difficulty-Needs-Investigation | Difficulty is not known. Issue needs further investigation beyond the triage session to establish a rating. | ## Version control system @@ -601,7 +510,6 @@ Available Tasks: ## Cookbook - The following sections have examples for some common procedures. ### Using the cli to examine and run unit tests, and creating the .expected file from a query diff --git a/docs/iso_26262_tool_qualification.md b/docs/iso_26262_tool_qualification.md index eb5ade738b..aea1b64463 100644 --- a/docs/iso_26262_tool_qualification.md +++ b/docs/iso_26262_tool_qualification.md @@ -1,19 +1,5 @@ # Software tool qualification under ISO 26262 -## Document management - -**Document ID:** codeql-coding-standards/iso-26262-tool-qualification - -| Version | Date | Author | Changes | -| ------- | ---------- | --------------- | ---------------------------------------------------------------------------------------- | -| 0.1.0 | 2021-09-07 | Luke Cartey | Initial version. | -| 0.2.0 | 2021-09-08 | Luke Cartey | Update CodeQL qualification methods. | -| 0.3.0 | 2021-09-08 | Luke Cartey | Update the customer table. | -| 0.4.0 | 2021-09-19 | Luke Cartey | Add more detail on approach to V&V. Update section around increased confidence from use. | -| 0.5.0 | 2021-11-29 | Remco Vermeulen | Add document management section. | - -## Introduction - A common use case for coding standards is in the verification and certification process for safety critical or low fault tolerance systems. The "CodeQL Coding Standards" product is therefore intended to be qualified as a "software tool" under "Part 8: Supporting processes" of ISO 26262 ("Road vehicles - Functional Safety"), to support use within the automotive industry as part of an ISO 26262 certification process. ## Tool confidence level @@ -106,13 +92,13 @@ In addition to testing on LGTM.com, we have also analyzed a further 748 C++ repo In addition, the following companies have publicly described their use of CodeQL for C++: -| Company | Creates CodeQL databases? | Runs default queries? | Runs custom queries? | References | -| ------------------------------ | ------------------------------------------------- | --------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Microsoft | Yes, including for Edge, Office 365, Windows etc. | Yes | Yes | https://semmle.com/case-studies/semmle-microsoft-vulnerability-hunting
    https://msrc-blog.microsoft.com/2019/11/06/vulnerability-hunting-with-semmle-ql-dom-xss/ | -| NASA | Yes | Yes | Yes | https://semmle.com/case-studies/semmle-nasa-landing-curiosity-safely-mars | -| Murex | Yes | Yes | Yes | https://semmle.com/case-studies/semmle-murex-securing-and-modernizing-worlds-leading-capital-markets-platform | -| Thermofisher | Yes | Yes | No | https://resources.github.com/webcasts/community-powered-security-developer-workflow-thankyou/
    https://github.blog/2020-07-15-how-organizations-can-tackle-securing-the-worlds-code/#make-sure-your-own-code-is-secure | -| Woven Planet (formerly TRI-AD) | Yes | Yes | Yes | https://www.youtube.com/watch?v=Twdftv0Tkfo | +| Company | Creates CodeQL databases? | Runs default queries? | Runs custom queries? | References | +| ------- | ------------------------- | --------------------- | -------------------- | ---------- | +| Microsoft | Yes, including for Edge, Office 365, Windows etc. | Yes | Yes | https://semmle.com/case-studies/semmle-microsoft-vulnerability-hunting
    https://msrc-blog.microsoft.com/2019/11/06/vulnerability-hunting-with-semmle-ql-dom-xss/ | +| NASA | Yes | Yes | Yes | https://semmle.com/case-studies/semmle-nasa-landing-curiosity-safely-mars | +| Murex | Yes | Yes | Yes | https://semmle.com/case-studies/semmle-murex-securing-and-modernizing-worlds-leading-capital-markets-platform | +| Thermofisher | Yes | Yes | No | https://resources.github.com/webcasts/community-powered-security-developer-workflow-thankyou/
    https://github.blog/2020-07-15-how-organizations-can-tackle-securing-the-worlds-code/#make-sure-your-own-code-is-secure | +| Woven Planet (formerly TRI-AD) | Yes | Yes | Yes | https://www.youtube.com/watch?v=Twdftv0Tkfo | This usage includes the analysis of a broad range and styles of C and C++ codebases, including some which are extremely large and complex. These customers continue to use the CodeQL tooling and make use of releases as and when they become available. diff --git a/docs/user_manual.md b/docs/user_manual.md index 2fd8227e65..4833236438 100644 --- a/docs/user_manual.md +++ b/docs/user_manual.md @@ -1,37 +1,5 @@ # CodeQL Coding Standards : User manual -## Document management - -**Document ID:** codeql-coding-standards/user-manual - -| Version | Date | Author | Changes | -| ------- | ---------- | --------------- | ----------------------------------------------------------------------------------------------------------------------- | -| 0.1.0 | 2021-08-24 | Luke Cartey | Initial version. | -| 0.2.0 | 2021-09-03 | Luke Cartey | Clarify the required SARIF version. | -| 0.3.0 | 2021-09-07 | Luke Cartey | Extract tool qualification into to separate document with id codeql-coding-standards/iso-26262-tool-qualification. | -| 0.4.0 | 2021-09-10 | Luke Cartey | Refine the use cases and failure modes. | -| 0.5.0 | 2021-09-19 | Luke Cartey | Clarify requirements of build command. Clarify the certification scope. Add false positives/negatives as failure modes. | -| 0.6.0 | 2021-11-16 | Remco Vermeulen | Add description of deviation records and analysis reports. | -| 0.7.0 | 2021-11-29 | Remco Vermeulen | Add document management section. Add release section. | -| 0.8.0 | 2022-02-06 | Remco Vermeulen | Add Hazard and Risk Analysis (HARA). Remove armclang support. | -| 0.9.0 | 2022-02-17 | Remco Vermeulen | Finalize scope deviation records | -| 0.10.0 | 2022-02-28 | Remco Vermeulen | Describe database correctness in the Hazard and Risk Analysis (HARA). | -| 0.11.0 | 2022-02-28 | Remco Vermeulen | Updated version to 1.1.0 | -| 0.12.0 | 2022-03-24 | John Singleton | Minor change to version strings and update of release artifacts list. | - -## Release information - -This user manual documents release `1.1.0` of the coding standards located at https://github.com/github/codeql-coding-standards/releases/tag/v1.1.0 . -The release page documents the release notes and contains the following artifacts part of the release: - -- `code-scanning-cpp-query-pack-anon-v1.1.0.zip`: coding standard queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. This package excludes AUTOSAR & MISRA copyrighted material. -- `code-scanning-cpp-query-pack-v1.1.0.zip`: coding standard queries and scripts to be used with GitHub Code Scanning or the CodeQL CLI as documented in the section _Operating manual_. -- `lgtm-cpp-query-pack-anon-v1.1.0.zip`: coding standard queries to be used with GitHub LGTM Enterprise as documented in the section _Operating manual_. This package excludes AUTOSAR & MISRA copyrighted material. -- `lgtm-cpp-query-pack-v1.1.0.zip`: coding standard queries to be used with GitHub LGTM Enterprise as documented in the section _Operating manual_. -- `supported_rules_list_v1.1.0.csv`: A Comma Separated File (CSV) containing the supported rules per standard and the queries that implement the rule. -- `supported_rules_list_v1.1.0.md`: A Markdown formatted file with a table containing the supported rules per standard and the queries that implement the rule. -- `user_manual.md`: This user manual. - ## Introduction ### Background @@ -44,10 +12,10 @@ A _coding standard_ is a set of rules or guidelines which restrict or prohibit t The _CodeQL Coding Standards_ product is a set of CodeQL queries for identifying contraventions of rules in the following coding standards: -| Standard | Version | Total rules | Total supportable rules | Status | -| -------------------------------------------------------------------------------------------------------------------- | ------- | ----------- | ----------------------- | ----------- | -| [AUTOSAR C++](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/20-11/AUTOSAR_RS_CPP14Guidelines.pdf) | 20-11 | 397 | 375 | Implemented | -| [CERT-C++](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf) | 2016 | 83 | 83 | Implemented | +| Standard | Version | Total rules | Total supportable rules | Status | +| -------------------------------------------------------------------------------------------------------------------- | ------- | ----------- | ----------------------- | -------------- | +| [AUTOSAR C++](https://www.autosar.org/fileadmin/user_upload/standards/adaptive/20-11/AUTOSAR_RS_CPP14Guidelines.pdf) | 20-11 | 397 | 375 | In development | +| [CERT-C++](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-cpp-coding-standard-2016-v01.pdf) | 2016 | 83 | 83 | In development | Not all rules in these standards are amenable to static analysis by CodeQL - some rules require external or domain specific knowledge to validate, or refer to properties which are not present in the our representation of the codebase under analysis. For each rule we therefore identify whether it is supportable or not. Furthermore, a rule can be supported in two ways: @@ -78,33 +46,21 @@ From a functional safety perspective, the use of these two components is only va The codebase under analysis must: * Comply with C++14 * Use one of the following supported compilers: - - Clang version 10 + - Clang (up to Clang 12.0) + - ARM C/C++ compiler (`armclang`) version 6 or later. Use of the queries outside these scenarios is possible, but not validated for functional safety. In particular: - Use of the queries against codebases written with more recent versions of C++ (as supported by CodeQL) are not validated in the following circumstances: - When new language features are used - When language features are used which have a differing interpretation from C++14. - - Use of the queries against codebases which use other compilers or other compiler versions supported by CodeQL (e.g. gcc) is not tested or validated for functional safety. + - Use of the queries against codebases which use other compilers supported by CodeQL (e.g. gcc) is not tested or validated for functional safety. In all scenarios, the codebase must comply with the language, platform and compiler requirements listed on the [CodeQL: Supported languages and frameworks](https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks) in order to be successfully analyzed. In addition, the machine which performs the analysis must be able to complete a clean build of the codebase. -### Analysis report requirements - -The Coding Standards ships with scripts to generate reports that summarizes: - - - The integrity and validity of the CodeQL database created for the project. - - The findings reported by the default queries for the selected Coding Standards, grouped by categories as specified by MISRA Compliance 2020. - - The CodeQL dependencies used for the analysis, and whether they comply with the stated requirements. - -The environment used to generate these reports requires: - -- A Python interpreter version 3.9 -- A CodeQL CLI version documented in the release artifact `supported_codeql_configs.json` ## Operating manual -This section describes how to operate the "CodeQL Coding Standards". ### Command line #### Pre-requisite: downloading the CodeQL CLI @@ -152,13 +108,11 @@ codeql database analyze --format=sarifv2.1.0 --output=.sar ``` For each Coding Standard you want to run, add a trailing entry in the following format: `path/to/codeql-coding-standards/cpp//src/codeql-suites/-default.qls`. -The only supported SARIF version for use in a functional safety environment is version 2.1.0. -To select this SARIF version you **must** specify the flag `--format=sarifv2.1.0` when invoking the database analyze command `codeql database analyze ...` as shown in the above example. +The only supported `--format` flag in a functional safety environment is `sarifv2.1.0`. -Running the default analysis for one or more Coding Standards may require further performance customizations for larger codebases. -The following flags may be passed to the `database analyze` command to adjust the performance: - - `--ram` - to specify the maximum amount of RAM to use during the analysis as [documented](https://codeql.github.com/docs/codeql-cli/manual/database-analyze/#options-to-control-ram-usage) in the CodeQL CLI manual. - - `--thread` - to specify number of threads to use while evaluating as [documented](https://codeql.github.com/docs/codeql-cli/manual/database-analyze/#cmdoption-codeql-database-analyze-j) in the CodeQL CLI manual. +Any other flags specified by the CodeQL CLI `database analyze` command may be used. In particular, larger codebases may require customizations to the following performance impacting flags: + - `--ram` - to specify the amount of RAM to use during the analysis + - `--thread` - to specify number of threads to use while evaluating The output of this command will be a [SARIF file](https://sarifweb.azurewebsites.net/) called `.sarif`. @@ -174,12 +128,12 @@ For each Coding Standard you want to run, add a trailing entry in the following #### Producing an analysis report -In addition to producing a results file, an analysis report can be produced that summarizes: +In addition to producing a results file, an analysis report can be produced that summarises: - The integrity and validity of the CodeQL database created for the project. - The findings reported by the default queries for the selected Coding Standards, grouped by categories as specified by MISRA Compliance 2020. - The CodeQL dependencies used for the analysis, and whether they comply with the stated requirements. -To run this script, the CodeQL CLI part of a supported CodeQL Bundle and Python interpreter version 3.9 must be available on the system path. +To run this script, a suitable CodeQL CLI and Python interpreter must be available on the system path. ``` python3 scripts/reports/analysis_report.py path/to/ .sarif @@ -192,7 +146,8 @@ This will produce a directory (``) containing the following re - Which Coding Standards were applied. - The versions of the CodeQL CLI, CodeQL Standard Library for C/C++ and the CodeQL Coding Standards queries used to perform the analysis. - Count of violations of guidelines by guideline category ("Required", "Advisory") - - A list of the guidelines checked, and the status of each guideline ("Compliant", "Violations", "Deviations"). + - A list of the guidelines checked, and the status of each guideline ("Compliant", "Violations", "Deviations" or "Disapplied"). + - In the current state the `Disapplied` status is not supported. - **Note:** The `Deviations` status is **only** shown when the database has been build with a configuration to *report deviated alerts* and analyzed with a *deviation alert suppression query*. The section on *Deviation records* outlines how this can be achieved. - An **Analysis Integrity Report** which summarizes any issues that were identified in the creation of the database, which can be reviewed to determine the extent to which these issues may have impacted the generated results. This includes: - A list of recoverable errors, where a specific piece of syntax was not handled, but the error could be recovered from. These a further sub-divided into "user code" errors and "third-party" errors. @@ -208,11 +163,14 @@ This will produce a directory (``) containing the following re - A textual description of background information. - A textual description of the requirements which must be satisfied to use the deviation. -#### Applying deviations +#### Applying deviations and guideline recategorisations + +_In development_ The CodeQL Coding Standards supports the following features from the [MISRA Compliance 2020](https://www.misra.org.uk/app/uploads/2021/06/MISRA-Compliance-2020.pdf) document: - _Deviation records_ - an entry that states a particular instance, or set of instances, of a rule should be considered permitted. - _Deviation permit_ - an entry that provides authorization to apply a deviation to a project. + - _Guideline re-categorization_ - each rule supported by a Coding Standard is allocated a "MISRA Guideline Category". A guideline re-categorization allows a different category to be applied. ##### Deviation records @@ -243,6 +201,8 @@ The current implementation of the `coding-standards.yml` specification supports - `name` - The name, handle or other identifier of the user who approved the request - `date` - The date on which they approved the request. +The current implementation **does not** use the `permit-identifier` property because the _deviation permit_ is not implemented. + The following code snippet provides an example of a `deviations` specification. ```yaml @@ -337,6 +297,11 @@ Unlike _deviation records_ their location in the source directory does not impac This means that _deviation permits_ can be made available at build time by any means available. An example of importing _deviation permits_ is through a [Git Submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) that contains a repository of allowed _deviation permits_. + +##### _Guideline re-categorization_ + +_In Development_ + ### GitHub Advanced Security and LGTM The only use cases that will be certified under ISO 26262 are those listed above. CodeQL Coding Standards is also compatible with, but not certified for, the following use cases: @@ -345,37 +310,21 @@ The only use cases that will be certified under ISO 26262 are those listed above - Uploading the SARIF results files for a CodeQL Coding Standards analysis to the GitHub [Code Scanning](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/about-code-scanning) feature. - Deployment of the default CodeQL Coding Standards queries as a custom query pack for [LGTM](https://semmle.com/lgtm). -### Hazard and risk analysis +### Known failure modes This section describes known failure modes for "CodeQL Coding Standards" and describes the impact, how the issue can be identified and what remediation steps can be followed to address the issue. -| Use case | Failure mode | Effect | Protective/detective measure | Remediation | -| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Installing CodeQL | Standard library not installed in the correct location. | Less output. The queries relying on the standard library cannot compile and not be executed. | Verify the availability of the required codeql/cpp-all QL pack with the command `codeql resolve qlpacks` or use a supported CodeQL bundle | Ensure a supported CodeQL bundle is used. | -| | Incompatible standard library installed. | Less output. The queries relying on a certain standard library version cannot compile and not be executed. | Use a supported CodeQL bundle | Ensure a supported CodeQL bundle is used. | -| | CodeQL installation modified (e.g., removing all extractors except for the cpp extractor) | Less output. Functionality such as reporting or the deviation mechanism relying on the availability of extractors other than the C++ extractor will fail. | Verify the availability of the required codeql/cpp-all QL pack with the command `codeql resolve qlpacks` and the availability of the cpp & xml extractors using the codeql command `codeql resolve extractor --language=cpp` & `codeql resolve extractor --language=xml` | Ensure a supported and unmodified CodeQL bundle is used. To prevent the downloading of the CodeQL bundle to dominate the total analysis time ensure it is available on the machine used to perform the analysis. | -| | Standard library modified | Less or more output. Results are reported that are not violations of the guidelines or guideline violations are not reported | Use the available CodeQL and CodeQL Coding Standards unit test to determine the queries work as expected with the provided standard library. | Ensure a supported and unmodified CodeQL bundle is used. To prevent the downloading of the CodeQL bundle to dominate the total analysis time ensure it is available on the machine used to perform the analysis. | -| | Incompatible runtime environment (e.g., `musl-c`) | Less output. Unable to observe compilation invocations preventing analysis. | Analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure a supported operating system is used and that the CodeQL requirements are met as listed on https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/ | -| Generating a CodeQL database | Compiler invocations are not observed | Less output. Unable to observe compilation invocations preventing analysis. | Analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure that the build system is not caching previous compilations (for example, using `ccache` or `bazel`) and that a supported compiler is being used. Issues can be reported via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Failure while processing a file or compilation | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Analysis integrity report lists the failures identified. | Recoverable errors impact only the specified portion of the code and anything that relies on it. Unrecoverable errors impact the specified file or compilation unit, and may impact other files whose analysis relies on that information. Issues can be reported via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Build command exits non-zero | Less output. No CodeQL database is created. | Error reported on the command line. | The underlying user provided build command failed. Ensure the build command succeeds outside of the CodeQL CLI. | -| | Incremental build | Less output. Some files may not be analyzed because they are not observed during the compilation process. | Analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure that the build system is configured to build from a clean state and disabled the use of a shared build cache. | -| | Distributed build | Less output. Some files may not be analyzed because they are not observed during the compilation process. | Analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure that the build system is configured to build locally. CodeQL does not support distributed builds. | -| | Containerized build | Less output or normal output. If misconfigured CodeQL will be unable to observe compilation invocations preventing analysis. | Error reported on the command line. CodeQL will either report the error `No source code was seen during the build` or exit with code `32` indicating that CodeQL was unable to monitor your code | Ensure CodeQL is configured to run in the container during the build as documented at https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/running-codeql-code-scanning-in-a-container | -| | Out of memory | Less output. No analysis results are produced | Error reported on the command line. | Increase memory, configure the CodeQL CLI to adhere to a memory limit, or report memory consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Timeout | Less output. No analysis results are produced | Analysis fails to complete, or is killed after a given time. | Report timeout issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Use of unsupported compiler | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. If no error is reported the analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure only compilers listed at https://codeql.github.com/docs/codeql-overview/supported-languages-and-frameworks/ are used. | -| | Use of incorrect build command | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure the build command corresponds to the build command that is used to build the release artifacts. | -| | Incorrect build environment (e.g., concurrent builds writing to same file, overwriting translation unit/object file with different content) | Less or more output. Results are reported that are not violations of the guidelines or guideline violations are not reported | All reported results must be reviewed. | Ensure the build environment is configured to not use shared resources such as caches or artifact providers that can introduce race conditions. Report inconsistent results via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Source root misspecification | Less output. The results cannot be correctly correlated to source files when viewing the resulting Sarif file in a Sarif viewer. | Verify that the reported results are display on the correct files in the Sarif viewer | Ensure the CodeQL CLI configured to use the correct source root that correspond to the root of the repository under consideration. | -| | Ouf of space | Less output. Some files may be only be partially analyzed, or not analyzed at all. | Error reported on the command line. | Increase space. If it remains an issue report space consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | False positives | More output. Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | False negatives | Less output. Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | -| | Modifying coding standard suite | More or less output. If queries are added to the query set more result can be reported. If queries are removed less results might be reported. | All queries supported by the CodeQL Coding Standards are listed in the release artifacts `supported_rules_list_VERSION.csv` where VERSION is replaced with the used release. The rules in the resulting Sarif file must be cross-referenced with the expected rules in this list to determine the validity of the used CodeQL suite. | Ensure that the CodeQL Coding Standards are not modified in ways that are not documented as supported modifications. | -| | Incorrect deviation record specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation records with a reason. Ensure that all deviation records are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | -| | Incorrect deviation permit specification | More output. Results are reported for guidelines for which a deviation is assigned. | Analysis integrity report lists all deviations and incorrectly specified deviation permits with a reason. Ensure that all deviation permits are correctly specified. | Ensure that the deviation record is specified according to the specification in the user manual. | -| | Unapproved use of a deviation record | Less output. Results for guideline violations are not reported. | Validate that the deviation record use is approved by verifying the approved-by attribute of the deviation record specification. | Ensure that each raised deviation record is approved by an independent approver through an auditable process. | -| | Incorrect database. The information extracted by the CodeQL extractor deviates from what the compiler extracts resulting in an incorrect model of the source-code. | More or less output. Incorrect extraction can result in false positives or false negatives. | Combinations of supported compilers and CodeQL CLIs are tested against a [provided](https://github.com/github/codeql/tree/main/cpp/ql/test/library-tests) suite of test cases and a coding standards specific test suite to determine if the extracted information deviates from the expected information. | Report incorrect database issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | +| Use case | Failure mode | Effect | Protective/detection measure | Remediation | +| ---------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Generating a CodeQL database | Compiler calls not observed | Some files will not be analyzed; no results will be reported in those files | Analysis integrity report lists all analyzed files, and must be crossed referenced with the list of files that are expected to be analyzed. | Ensure that the build system is not caching previous compilations (for example, using ccache or bazel) and that a supported compiler is being used. Issues can be reported via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | +| | Failure while processing a file or compilation | Some files may be only be partially analyzed, or not analyzed at all. | Analysis integrity report lists the failures identified. | Recoverable errors impact only the specified portion of the code and anything that relies on it. Unrecoverable errors impact the specified file or compilation unit, and may impact other files whose analysis relies on that information. Issues can be reported via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | +| | Build command exits non-zero | No CodeQL database is created | Error reported on the command line. | The underlying user provided build command failed. Ensure the build command succeeds outside of the CodeQL CLI. | +| Running the analyses | Out of memory | No analysis results are produced | Error reported on the command line. | Increase memory, configure the CodeQL CLI to adhere to a memory limit, or report memory consumption issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | +| | Timeout | No analysis results are produced | Analysis fails to complete, or is killed after a given time. | Report timeout issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | +| | False positives | Results are reported which are not violations of the guidelines. | All reported results must be reviewed. | Report false positive issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | +| | False negatives | Violations of the guidelines are not reported. | Other validation and verification processes during software development should be used to complement the analysis performed by CodeQL Coding Standards. | Report false negative issues via the CodeQL Coding Standards [bug tracker](https://github.com/github/codeql-coding-standards/issues). | + + ## Reporting bugs A bug tracker is provided on the [`github/codeql-coding-standards`](https://github.com/github/codeql-coding-standards) repository [issues page](https://github.com/github/codeql-coding-standards/issues). New issues can be filed on the [New Issues](https://github.com/github/codeql-coding-standards/issues/new/choose) page. diff --git a/rule_packages/c/IO1.json b/rule_packages/c/IO1.json new file mode 100644 index 0000000000..2de76a3961 --- /dev/null +++ b/rule_packages/c/IO1.json @@ -0,0 +1,139 @@ +{ + "CERT-C": { + "FIO30-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "Never call a formatted I/O function with a format string containing user input.", + "kind": "problem", + "name": "Exclude user input from format strings", + "precision": "high", + "severity": "error", + "short_name": "ExcludeUserInputFromFormatStrings", + "shared_implementation_short_name": "NonConstantFormat", + "tags": [ + "correctness", + "security" + ] + } + ], + "title": "Exclude user input from format strings" + }, + "FIO34-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "File read should be followed by a check for read errors and end of file.", + "kind": "problem", + "name": "Distinguish between characters read from a file and EOF or WEOF", + "precision": "high", + "severity": "error", + "short_name": "DistinguishBetweenCharReadFromAFileAndEofOrWeof", + "tags": [ + "correctness", + "security" + ] + }, + { + "description": "Checks against EOF are only portable to platforms where type `char` is less wide than type `int`.", + "kind": "problem", + "name": "Checks against EOF and WEOF are not portable", + "precision": "high", + "severity": "warning", + "short_name": "EndOfFileCheckPortability", + "tags": [ + "correctness", + "security" + ] + } + ], + "title": "Distinguish between characters read from a file and EOF or WEOF" + }, + "FIO39-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "", + "kind": "problem", + "name": "Do not alternately input and output from a stream without an intervening flush or positioning call", + "precision": "very-high", + "severity": "error", + "short_name": "DoNotAlternatelyIOFromAStreamWithoutPositioning", + "shared_implementation_short_name": "IOFstreamMissingPositioning", + "tags": [ + "correctness" + ] + } + ], + "title": "Do not alternately input and output from a stream without an intervening flush or positioning call" + }, + "FIO42-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "", + "kind": "problem", + "name": "Close files when they are no longer needed", + "precision": "very-high", + "severity": "error", + "short_name": "CloseFilesWhenTheyAreNoLongerNeeded", + "tags": [ + "correctness", + "security" + ] + } + ], + "title": "Close files when they are no longer needed" + }, + "FIO46-C": { + "properties": { + "obligation": "rule" + }, + "queries": [ + { + "description": "Do not access a closed file", + "kind": "problem", + "name": "Do not access a closed file", + "precision": "high", + "severity": "error", + "short_name": "UndefinedBehaviorAccessingAClosedFile", + "shared_implementation_short_name": "DoNotAccessAClosedFile", + "tags": [ + "correctness" + ] + } + ], + "title": "Do not access a closed file" + } + }, + "MISRA-C-2012": { + "RULE-22-6": { + "properties": { + "obligation": "mandatory" + }, + "queries": [ + { + "description": "A closed FILE is accessed", + "kind": "problem", + "name": "The value of a pointer to a FILE shall not be used after the associated stream has been closed", + "precision": "very-high", + "severity": "error", + "short_name": "FileUsedAfterClosed", + "shared_implementation_short_name": "DoNotAccessAClosedFile", + "tags": [ + "correctness" + ] + } + ], + "title": "The value of a pointer to a FILE shall not be used after the associated stream has been closed" + } + } +} diff --git a/rule_packages/c/Preprocessor1.json b/rule_packages/c/Preprocessor1.json new file mode 100644 index 0000000000..21ad88ea15 --- /dev/null +++ b/rule_packages/c/Preprocessor1.json @@ -0,0 +1,85 @@ +{ + "MISRA-C-2012": { + "RULE-20-1": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "Using anything other than other pre-processor directives or comments before an '#include' directive makes the code more difficult to read.", + "kind": "problem", + "name": "#include directives should only be preceded by preprocessor directives or comments", + "precision": "very-high", + "severity": "warning", + "short_name": "IncludeDirectivesPrecededByDirectivesOrComments", + "shared_implementation_short_name": "PreprocessorIncludesPreceded", + "tags": [ + "readability" + ] + } + ], + "title": "#include directives should only be preceded by preprocessor directives or comments" + }, + "RULE-20-10": { + "properties": { + "obligation": "advisory" + }, + "queries": [ + { + "description": "The order of evaluation for the '#' and '##' operators may differ between compilers, which can cause unexpected behaviour.", + "kind": "problem", + "name": "The # and ## preprocessor operators should not be used", + "precision": "very-high", + "severity": "warning", + "short_name": "PreprocessorHashOperatorsShouldNotBeUsed", + "shared_implementation_short_name": "HashOperatorsUsed", + "tags": [ + "correctness" + ] + } + ], + "title": "The # and ## preprocessor operators should not be used" + }, + "RULE-20-2": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Using any of the following characters in an '#include' directive as a part of the header file name is undefined behaviour: ', \", /*, //, \\.", + "kind": "problem", + "name": "The ', \" or \\ characters and the /* or // character sequences shall not occur in a header file name", + "precision": "very-high", + "severity": "error", + "short_name": "ForbiddenCharactersInHeaderFileName", + "shared_implementation_short_name": "PreprocessorIncludesForbiddenHeaderNames", + "tags": [ + "correctness" + ] + } + ], + "title": "The ', \" or \\ characters and the /* or // character sequences shall not occur in a header file name" + }, + "RULE-20-9": { + "properties": { + "obligation": "required" + }, + "queries": [ + { + "description": "Using undefined macro identifiers in #if or #elif pre-processor directives, except as operands to the defined operator, can cause the code to be hard to understand because the preprocessor will just treat the value as 0 and no warning is given.", + "kind": "problem", + "name": "All identifiers used in the controlling expression of #if or #elif preprocessing directives shall be", + "precision": "high", + "severity": "warning", + "short_name": "IdentifiersUsedInPreprocessorExpression", + "shared_implementation_short_name": "UndefinedMacroIdentifiers", + "tags": [ + "correctness", + "readability" + ] + } + ], + "title": "All identifiers used in the controlling expression of #if or #elif preprocessing directives shall be #define\ufffdd before evaluation" + } + } +} \ No newline at end of file diff --git a/rule_packages/Allocations.json b/rule_packages/cpp/Allocations.json similarity index 100% rename from rule_packages/Allocations.json rename to rule_packages/cpp/Allocations.json diff --git a/rule_packages/BannedFunctions.json b/rule_packages/cpp/BannedFunctions.json similarity index 100% rename from rule_packages/BannedFunctions.json rename to rule_packages/cpp/BannedFunctions.json diff --git a/rule_packages/BannedLibraries.json b/rule_packages/cpp/BannedLibraries.json similarity index 100% rename from rule_packages/BannedLibraries.json rename to rule_packages/cpp/BannedLibraries.json diff --git a/rule_packages/BannedSyntax.json b/rule_packages/cpp/BannedSyntax.json similarity index 100% rename from rule_packages/BannedSyntax.json rename to rule_packages/cpp/BannedSyntax.json diff --git a/rule_packages/BannedTypes.json b/rule_packages/cpp/BannedTypes.json similarity index 100% rename from rule_packages/BannedTypes.json rename to rule_packages/cpp/BannedTypes.json diff --git a/rule_packages/Classes.json b/rule_packages/cpp/Classes.json similarity index 100% rename from rule_packages/Classes.json rename to rule_packages/cpp/Classes.json diff --git a/rule_packages/Comments.json b/rule_packages/cpp/Comments.json similarity index 100% rename from rule_packages/Comments.json rename to rule_packages/cpp/Comments.json diff --git a/rule_packages/Concurrency.json b/rule_packages/cpp/Concurrency.json similarity index 100% rename from rule_packages/Concurrency.json rename to rule_packages/cpp/Concurrency.json diff --git a/rule_packages/Conditionals.json b/rule_packages/cpp/Conditionals.json similarity index 100% rename from rule_packages/Conditionals.json rename to rule_packages/cpp/Conditionals.json diff --git a/rule_packages/Const.json b/rule_packages/cpp/Const.json similarity index 100% rename from rule_packages/Const.json rename to rule_packages/cpp/Const.json diff --git a/rule_packages/DeadCode.json b/rule_packages/cpp/DeadCode.json similarity index 100% rename from rule_packages/DeadCode.json rename to rule_packages/cpp/DeadCode.json diff --git a/rule_packages/Declarations.json b/rule_packages/cpp/Declarations.json similarity index 100% rename from rule_packages/Declarations.json rename to rule_packages/cpp/Declarations.json diff --git a/rule_packages/ExceptionSafety.json b/rule_packages/cpp/ExceptionSafety.json similarity index 100% rename from rule_packages/ExceptionSafety.json rename to rule_packages/cpp/ExceptionSafety.json diff --git a/rule_packages/Exceptions1.json b/rule_packages/cpp/Exceptions1.json similarity index 100% rename from rule_packages/Exceptions1.json rename to rule_packages/cpp/Exceptions1.json diff --git a/rule_packages/Exceptions2.json b/rule_packages/cpp/Exceptions2.json similarity index 100% rename from rule_packages/Exceptions2.json rename to rule_packages/cpp/Exceptions2.json diff --git a/rule_packages/Expressions.json b/rule_packages/cpp/Expressions.json similarity index 100% rename from rule_packages/Expressions.json rename to rule_packages/cpp/Expressions.json diff --git a/rule_packages/Freed.json b/rule_packages/cpp/Freed.json similarity index 95% rename from rule_packages/Freed.json rename to rule_packages/cpp/Freed.json index 3f2fbace14..bc3946b1da 100644 --- a/rule_packages/Freed.json +++ b/rule_packages/cpp/Freed.json @@ -53,7 +53,8 @@ "short_name": "ObjectAccessedBeforeLifetimeAutosar", "tags": [ "correctness", - "security" + "security", + "external/autosar/default-disabled" ] }, { @@ -66,7 +67,8 @@ "short_name": "ObjectAccessedAfterLifetimeAutosar", "tags": [ "correctness", - "security" + "security", + "external/autosar/default-disabled" ] } ], @@ -131,7 +133,8 @@ "short_name": "ObjectAccessedBeforeLifetimeCert", "tags": [ "correctness", - "security" + "security", + "external/autosar/default-disabled" ] }, { @@ -144,7 +147,8 @@ "short_name": "ObjectAccessedAfterLifetimeCert", "tags": [ "correctness", - "security" + "security", + "external/autosar/default-disabled" ] } ], diff --git a/rule_packages/Functions.json b/rule_packages/cpp/Functions.json similarity index 100% rename from rule_packages/Functions.json rename to rule_packages/cpp/Functions.json diff --git a/rule_packages/IO.json b/rule_packages/cpp/IO.json similarity index 100% rename from rule_packages/IO.json rename to rule_packages/cpp/IO.json diff --git a/rule_packages/Includes.json b/rule_packages/cpp/Includes.json similarity index 100% rename from rule_packages/Includes.json rename to rule_packages/cpp/Includes.json diff --git a/rule_packages/Inheritance.json b/rule_packages/cpp/Inheritance.json similarity index 100% rename from rule_packages/Inheritance.json rename to rule_packages/cpp/Inheritance.json diff --git a/rule_packages/Initialization.json b/rule_packages/cpp/Initialization.json similarity index 100% rename from rule_packages/Initialization.json rename to rule_packages/cpp/Initialization.json diff --git a/rule_packages/IntegerConversion.json b/rule_packages/cpp/IntegerConversion.json similarity index 100% rename from rule_packages/IntegerConversion.json rename to rule_packages/cpp/IntegerConversion.json diff --git a/rule_packages/Invariants.json b/rule_packages/cpp/Invariants.json similarity index 100% rename from rule_packages/Invariants.json rename to rule_packages/cpp/Invariants.json diff --git a/rule_packages/Iterators.json b/rule_packages/cpp/Iterators.json similarity index 100% rename from rule_packages/Iterators.json rename to rule_packages/cpp/Iterators.json diff --git a/rule_packages/Lambdas.json b/rule_packages/cpp/Lambdas.json similarity index 100% rename from rule_packages/Lambdas.json rename to rule_packages/cpp/Lambdas.json diff --git a/rule_packages/Literals.json b/rule_packages/cpp/Literals.json similarity index 100% rename from rule_packages/Literals.json rename to rule_packages/cpp/Literals.json diff --git a/rule_packages/Loops.json b/rule_packages/cpp/Loops.json similarity index 100% rename from rule_packages/Loops.json rename to rule_packages/cpp/Loops.json diff --git a/rule_packages/Macros.json b/rule_packages/cpp/Macros.json similarity index 97% rename from rule_packages/Macros.json rename to rule_packages/cpp/Macros.json index e0f4c25f7c..dc4d22047b 100644 --- a/rule_packages/Macros.json +++ b/rule_packages/cpp/Macros.json @@ -41,6 +41,7 @@ "precision": "very-high", "severity": "error", "short_name": "CharactersOccurInHeaderFileNameOrInIncludeDirective", + "shared_implementation_short_name": "PreprocessorIncludesForbiddenHeaderNames", "tags": [ "correctness" ] @@ -111,6 +112,7 @@ "precision": "very-high", "severity": "warning", "short_name": "IncludeDirectivesNotPrecededByDirectivesOrComments", + "shared_implementation_short_name": "PreprocessorIncludesPreceded", "tags": [ "readability" ] @@ -205,6 +207,7 @@ "precision": "high", "severity": "warning", "short_name": "UndefinedMacroIdentifiersUsedIn", + "shared_implementation_short_name": "UndefinedMacroIdentifiers", "tags": [ "correctness", "readability" @@ -275,6 +278,7 @@ "precision": "very-high", "severity": "warning", "short_name": "HashOperatorsShouldNotBeUsed", + "shared_implementation_short_name": "HashOperatorsUsed", "tags": [ "correctness" ] diff --git a/rule_packages/MoveForward.json b/rule_packages/cpp/MoveForward.json similarity index 100% rename from rule_packages/MoveForward.json rename to rule_packages/cpp/MoveForward.json diff --git a/rule_packages/Naming.json b/rule_packages/cpp/Naming.json similarity index 100% rename from rule_packages/Naming.json rename to rule_packages/cpp/Naming.json diff --git a/rule_packages/Null.json b/rule_packages/cpp/Null.json similarity index 93% rename from rule_packages/Null.json rename to rule_packages/cpp/Null.json index 5e9cbcf4d5..c10d34f943 100644 --- a/rule_packages/Null.json +++ b/rule_packages/cpp/Null.json @@ -17,7 +17,8 @@ "severity": "error", "short_name": "NullPointersDereferenced", "tags": [ - "correctness" + "correctness", + "external/autosar/default-disabled" ] } ], @@ -62,7 +63,8 @@ "severity": "error", "short_name": "DoNotAttemptToCreateAStringFromANullPointer", "tags": [ - "correctness" + "correctness", + "external/cert/default-disabled" ] } ], diff --git a/rule_packages/OperatorInvariants.json b/rule_packages/cpp/OperatorInvariants.json similarity index 100% rename from rule_packages/OperatorInvariants.json rename to rule_packages/cpp/OperatorInvariants.json diff --git a/rule_packages/Operators.json b/rule_packages/cpp/Operators.json similarity index 100% rename from rule_packages/Operators.json rename to rule_packages/cpp/Operators.json diff --git a/rule_packages/OrderOfEvaluation.json b/rule_packages/cpp/OrderOfEvaluation.json similarity index 100% rename from rule_packages/OrderOfEvaluation.json rename to rule_packages/cpp/OrderOfEvaluation.json diff --git a/rule_packages/OutOfBounds.json b/rule_packages/cpp/OutOfBounds.json similarity index 100% rename from rule_packages/OutOfBounds.json rename to rule_packages/cpp/OutOfBounds.json diff --git a/rule_packages/Pointers.json b/rule_packages/cpp/Pointers.json similarity index 100% rename from rule_packages/Pointers.json rename to rule_packages/cpp/Pointers.json diff --git a/rule_packages/Representation.json b/rule_packages/cpp/Representation.json similarity index 100% rename from rule_packages/Representation.json rename to rule_packages/cpp/Representation.json diff --git a/rule_packages/Scope.json b/rule_packages/cpp/Scope.json similarity index 100% rename from rule_packages/Scope.json rename to rule_packages/cpp/Scope.json diff --git a/rule_packages/SideEffects1.json b/rule_packages/cpp/SideEffects1.json similarity index 100% rename from rule_packages/SideEffects1.json rename to rule_packages/cpp/SideEffects1.json diff --git a/rule_packages/SideEffects2.json b/rule_packages/cpp/SideEffects2.json similarity index 100% rename from rule_packages/SideEffects2.json rename to rule_packages/cpp/SideEffects2.json diff --git a/rule_packages/SmartPointers1.json b/rule_packages/cpp/SmartPointers1.json similarity index 100% rename from rule_packages/SmartPointers1.json rename to rule_packages/cpp/SmartPointers1.json diff --git a/rule_packages/SmartPointers2.json b/rule_packages/cpp/SmartPointers2.json similarity index 100% rename from rule_packages/SmartPointers2.json rename to rule_packages/cpp/SmartPointers2.json diff --git a/rule_packages/Strings.json b/rule_packages/cpp/Strings.json similarity index 100% rename from rule_packages/Strings.json rename to rule_packages/cpp/Strings.json diff --git a/rule_packages/Templates.json b/rule_packages/cpp/Templates.json similarity index 100% rename from rule_packages/Templates.json rename to rule_packages/cpp/Templates.json diff --git a/rule_packages/Toolchain.json b/rule_packages/cpp/Toolchain.json similarity index 100% rename from rule_packages/Toolchain.json rename to rule_packages/cpp/Toolchain.json diff --git a/rule_packages/TrustBoundaries.json b/rule_packages/cpp/TrustBoundaries.json similarity index 100% rename from rule_packages/TrustBoundaries.json rename to rule_packages/cpp/TrustBoundaries.json diff --git a/rule_packages/TypeRanges.json b/rule_packages/cpp/TypeRanges.json similarity index 99% rename from rule_packages/TypeRanges.json rename to rule_packages/cpp/TypeRanges.json index c67a1d6c52..1c073310da 100644 --- a/rule_packages/TypeRanges.json +++ b/rule_packages/cpp/TypeRanges.json @@ -97,6 +97,7 @@ "precision": "high", "severity": "error", "short_name": "InputsFromIndependentComponentsNotValidated", + "shared_implementation_short_name": "NonConstantFormat", "tags": [ "correctness", "security" diff --git a/rule_packages/Uninitialized.json b/rule_packages/cpp/Uninitialized.json similarity index 100% rename from rule_packages/Uninitialized.json rename to rule_packages/cpp/Uninitialized.json diff --git a/rule_packages/VirtualFunctions.json b/rule_packages/cpp/VirtualFunctions.json similarity index 100% rename from rule_packages/VirtualFunctions.json rename to rule_packages/cpp/VirtualFunctions.json diff --git a/rules.csv b/rules.csv index 0616a79511..005e9c9171 100755 --- a/rules.csv +++ b/rules.csv @@ -1,481 +1,776 @@ -Standard,ID,Queryable?,Obligation level,Enforcement level,Allocated target,Description,Similar,Package,Difficulty,Justification for querability level -AUTOSAR,A0-1-1,Yes,Required,Automated,Implementation,A project shall not contain instances of non-volatile variables being given values that are not subsequently used.,M0-1-6,DeadCode,Medium, -AUTOSAR,A0-1-2,Yes,Required,Automated,Implementation,The value returned by a function having a non-void return type that is not an overloaded operator shall be used.,M0-1-7,DeadCode,Easy, -AUTOSAR,A0-1-3,Yes,Required,Automated,Implementation,"Every function defined in an anonymous namespace, or static function with internal linkage, or private member function shall be used.",M0-1-10,DeadCode,Easy, -AUTOSAR,A0-1-4,Yes,Required,Automated,Implementation,There shall be no unused named parameters in non-virtual functions.,,DeadCode,Easy, -AUTOSAR,A0-1-5,Yes,Required,Automated,Implementation,There shall be no unused named parameters in the set of parameters for a virtual function and all the functions that override it.,,DeadCode,Easy, -AUTOSAR,A0-1-6,Yes,Advisory,Automated,Implementation,There should be no unused type declarations.,M0-1-5,DeadCode,Easy, -AUTOSAR,A0-4-1,Yes,Required,Non-Automated,Infrastructure / Toolchain,Floating-point implementation shall comply with IEEE 754 standard.,,Toolchain,Easy,Find certain pairs of types and platforms which are not IEEE 754 compatible. -AUTOSAR,A0-4-2,Yes,Required,Automated,Implementation,Type long double shall not be used.,,BannedTypes,Easy, -AUTOSAR,A0-4-3,Yes,Required,Automated,Toolchain,The implementations in the chosen compiler shall strictly comply with the C++14 Language Standard.,,Toolchain,Easy,Find cases where -std=gnu++14 is used instead of -std=c++14. Note: this is currently only possible for compilations that do not use response files. -AUTOSAR,A0-4-4,Yes,Required,Partially Automated,Implementation,"Range, domain and pole errors shall be checked when using math functions.",,TypeRanges,Hard, -AUTOSAR,A1-1-1,Yes,Required,Automated,Implementation,All code shall conform to ISO/IEC 14882:2014 - Programming Language C++ and shall not use deprecated features.,,Toolchain,Hard,"Appendix D of the Standard lists depreceated features. List is lengthy, but otherwise easy to write. This can also be compiler checked, so we should confirm that we also want this as a CodeQL check." -AUTOSAR,A1-1-2,Yes,Required,Non-Automated,Implementation / Toolchain,A warning level of the compilation process shall be set in compliance with project policies.,,Toolchain,Easy,Note: this is currently only possible for compilations that do not use response files. -AUTOSAR,A1-1-3,Yes,Required,Non-Automated,Toolchain,An optimization option that disregards strict standard compliance shall not be turned on in the chosen compiler.,,Toolchain,Easy,Note: this is currently only possible for compilations that do not use response files. -AUTOSAR,A1-2-1,No,Required,Non-Automated,Toolchain,"When using a compiler toolchain (including preprocessor, compiler itself, linker, C++ standard libraries) in safety-related software, the tool confidence level (TCL) shall be determined. In case of TCL2 or TCL3, the compiler shall undergo a 'Qualification of a software tool', as per ISO 26262-8.11.4.6 [6].",,,,Allocated target not covered by CodeQL -AUTOSAR,A1-4-1,No,Required,Non-Automated,Implementation / Verification,Code metrics and their valid boundaries shall be defined and code shall comply with defined boundaries of code metrics.,,,,Allocated target not covered by CodeQL -AUTOSAR,A1-4-3,No,Advisory,Automated,Implementation,All code should compile free of compiler warnings.,,,,"This should be checked via the compiler output, rather than CodeQL, which adds unecessary steps." -AUTOSAR,A10-0-1,Yes,Required,Non-Automated,Design,Public inheritance shall be used to implement 'is-a' relationship.,,Inheritance,Audit,Report a list of Inheritance relationships. -AUTOSAR,A10-0-2,Yes,Required,Non-Automated,Design,Membership or non-public inheritance shall be used to implement 'has-a' relationship.,,Inheritance,Audit,Report a list of membership relationships. -AUTOSAR,A10-1-1,Yes,Required,Automated,Implementation,Class shall not be derived from more than one base class which is not an interface class.,,Inheritance,Easy, -AUTOSAR,A10-2-1,Yes,Required,Automated,Implementation,Non-virtual public or protected member functions shall not be redefined in derived classes.,,VirtualFunctions,Easy, -AUTOSAR,A10-3-1,Yes,Required,Automated,Implementation,"Virtual function declaration shall contain exactly one of the three specifiers: (1) virtual, (2) override, (3) final.",,VirtualFunctions,Easy, -AUTOSAR,A10-3-2,Yes,Required,Automated,Implementation,Each overriding virtual function shall be declared with the override or final specifier.,,VirtualFunctions,Easy, -AUTOSAR,A10-3-3,Yes,Required,Automated,Implementation,Virtual functions shall not be introduced in a final class.,,VirtualFunctions,Easy, -AUTOSAR,A10-3-5,Yes,Required,Automated,Implementation,A user-defined assignment operator shall not be virtual.,,Operators,Easy, -AUTOSAR,A10-4-1,Yes,Advisory,Non-Automated,Design,Hierarchies should be based on interface classes.,,Inheritance,Audit,Report a list of hierarchies which don't use interfaces. -AUTOSAR,A11-0-1,Yes,Advisory,Automated,Implementation,A non-POD type should be defined as class.,,Classes,Easy, -AUTOSAR,A11-0-2,Yes,Required,Automated,Implementation,"A type defined as struct shall: (1) provide only public data members, (2) not provide any special member functions or methods, (3) not be a base of another struct or class, (4) not inherit from another struct or class.",,Classes,Easy, -AUTOSAR,A11-3-1,Yes,Required,Automated,Implementation,Friend declarations shall not be used.,cpp/jsf/av-rule-70,BannedSyntax,Easy, -AUTOSAR,A12-0-1,Yes,Required,Automated,Implementation,"If a class declares a copy or move operation, or a destructor, either via '=default', '=delete', or via a user-provided declaration, then all others of these five special member functions shall be declared as well.",cpp/rule-of-three,Classes,Easy, -AUTOSAR,A12-0-2,Yes,Required,Partially Automated,Implementation,Bitwise operations and operations that assume data representation in memory shall not be performed on objects.,M5-0-21,Expressions,Medium, -AUTOSAR,A12-1-1,Yes,Required,Automated,Implementation,"Constructors shall explicitly initialize all virtual base classes, all direct non-virtual base classes and all non-static data members.",M12-1-2,Initialization,Medium, -AUTOSAR,A12-1-2,Yes,Required,Automated,Implementation,Both NSDMI and a non-static member initializer in a constructor shall not be used in the same type.,,Initialization,Medium, -AUTOSAR,A12-1-3,Yes,Required,Automated,Implementation,"If all user-defined constructors of a class initialize data members with constant values that are the same across all constructors, then data members shall be initialized using NSDMI instead.",,Initialization,Medium, -AUTOSAR,A12-1-4,Yes,Required,Automated,Implementation,All constructors that are callable with a single argument of fundamental type shall be declared explicit.,,Initialization,Easy, -AUTOSAR,A12-1-5,Yes,Required,Partially Automated,Implementation,Common class initialization for non-constant members shall be done by a delegating constructor.,,Initialization,Medium, -AUTOSAR,A12-1-6,Yes,Required,Automated,Implementation,Derived classes that do not need further explicit initialization and require all the constructors from the base class shall use inheriting constructors.,,Initialization,Easy, -AUTOSAR,A12-4-1,Yes,Required,Automated,Implementation,"Destructor of a base class shall be public virtual, public override or protected non-virtual.",OOP52-CPP,VirtualFunctions,Easy, -AUTOSAR,A12-4-2,Yes,Advisory,Automated,Implementation,"If a public destructor of a class is non-virtual, then the class should be declared final.",,VirtualFunctions,Easy, -AUTOSAR,A12-6-1,Yes,Required,Automated,Implementation,All class data members that are initialized by the constructor shall be initialized using member initializers.,,Classes,Easy, -AUTOSAR,A12-7-1,Yes,Required,Automated,Implementation,"If the behavior of a user-defined special member function is identical to implicitly defined special member function, then it shall be defined '=default' or be left undefined.",,Classes,Easy, -AUTOSAR,A12-8-1,Yes,Required,Automated,Implementation,"Move and copy constructors shall move and respectively copy base classes and data members of a class, without any side effects.",M12-8-1,SideEffects2,Hard, -AUTOSAR,A12-8-2,Yes,Advisory,Automated,Implementation,User-defined copy and move assignment operators should use user-defined no-throw swap function.,,OperatorInvariants,Easy, -AUTOSAR,A12-8-3,Yes,Required,Partially Automated,Implementation,Moved-from object shall not be read-accessed.,EXP63-CPP,MoveForward,Import, -AUTOSAR,A12-8-4,Yes,Required,Automated,Implementation,Move constructor shall not initialize its class members and base classes using copy semantics.,,Initialization,Easy, -AUTOSAR,A12-8-5,Yes,Required,Automated,Implementation,A copy assignment and a move assignment operators shall handle self-assignment.,OOP54-CPP,OperatorInvariants,Import, -AUTOSAR,A12-8-6,Yes,Required,Automated,Implementation,Copy and move constructors and copy assignment and move assignment operators shall be declared protected or defined '=delete' in base class.,M12-8-2,Operators,Easy, -AUTOSAR,A12-8-7,Yes,Advisory,Automated,Implementation,Assignment operators should be declared with the ref-qualifier &.,,Operators,Easy, -AUTOSAR,A13-1-2,Yes,Required,Automated,Implementation,User defined suffixes of the user defined literal operators shall start with underscore followed by one or more letters.,,Naming,Easy, -AUTOSAR,A13-1-3,Yes,Required,Automated,Implementation,User defined literals operators shall only perform conversion of passed parameters.,,SideEffects2,Easy, -AUTOSAR,A13-2-1,Yes,Required,Automated,Implementation,An assignment operator shall return a reference to 'this'.,cpp/assignment-does-not-return-this,OperatorInvariants,Easy, -AUTOSAR,A13-2-2,Yes,Required,Automated,Implementation,A binary arithmetic operator and a bitwise operator shall return a 'prvalue'.,,OperatorInvariants,Easy, -AUTOSAR,A13-2-3,Yes,Required,Automated,Implementation,A relational operator shall return a boolean value.,,Operators,Easy, -AUTOSAR,A13-3-1,Yes,Required,Automated,Implementation,A function that contains 'forwarding reference' as its argument shall not be overloaded.,,Operators,Easy, -AUTOSAR,A13-5-1,Yes,Required,Automated,Implementation,"If 'operator[]' is to be overloaded with a non-const version, const version shall also be implemented.",,Operators,Easy, -AUTOSAR,A13-5-2,Yes,Required,Automated,Implementation,All user-defined conversion operators shall be defined explicit.,,Operators,Easy, -AUTOSAR,A13-5-3,Yes,Advisory,Automated,Implementation,User-defined conversion operators should not be used.,,Operators,Easy, -AUTOSAR,A13-5-4,Yes,Required,Automated,Implementation,"If two opposite operators are defined, one shall be defined in terms of the other.",,OperatorInvariants,Easy, -AUTOSAR,A13-5-5,Yes,Required,Automated,Implementation,Comparison operators shall be non-member functions with identical parameter types and noexcept.,,Operators,Easy, -AUTOSAR,A13-6-1,Yes,Required,Automated,Implementation,"Digit sequences separators ' shall only be used as follows: (1) for decimal, every 3 digits, (2) for hexadecimal, every 2 digits, (3) for binary, every 4 digits.",,Literals,Easy, -AUTOSAR,A14-1-1,Yes,Advisory,Non-Automated,Implementation,A template should check if a specific template argument is suitable for this template.,,Templates,Medium,"Look for classes with default constructors or assignment operators, with a template field which is not copyable/moveable" -AUTOSAR,A14-5-1,Yes,Required,Automated,Implementation,A template constructor shall not participate in overload resolution for a single argument of the enclosing class type.,M14-5-2,Templates,Easy, -AUTOSAR,A14-5-2,Yes,Advisory,Partially-Automated,Design,Class members that are not dependent on template class parameters should be defined in a separate base class.,,Classes,Easy, -AUTOSAR,A14-5-3,Yes,Advisory,Automated,Design,"A non-member generic operator shall only be declared in a namespace that does not contain class (struct) type, enum type or union type declarations.",,Operators,Easy, -AUTOSAR,A14-7-1,Yes,Required,Automated,Implementation,A type used as a template argument shall provide all members that are used by the template.,M14-7-2,Templates,Easy, -AUTOSAR,A14-7-2,Yes,Required,Automated,Implementation,"Template specialization shall be declared in the same file (1) as the primary template (2) as a user-defined type, for which the specialization is declared.",,Templates,Easy, -AUTOSAR,A14-8-2,Yes,Required,Automated,Implementation,Explicit specializations of function templates shall not be used.,M14-8-1,Templates,Easy, -AUTOSAR,A15-0-1,Yes,Required,Non-Automated,Architecture / Design / Implementation,A function shall not exit with an exception if it is able to complete its task.,,Exceptions1,Audit,Report a list of functions which throw exceptions. -AUTOSAR,A15-0-2,Yes,Required,Partially Automated,Architecture / Design / Implementation,"At least the basic guarantee for exception safety shall be provided for all operations. In addition, each function may offer either the strong guarantee or the nothrow guarantee",ERR56-CPP,ExceptionSafety,Import, -AUTOSAR,A15-0-3,Yes,Required,Non-Automated,Implementation,Exception safety guarantee of a called function shall be considered.,,ExceptionSafety,Hard,"There are certain exception safety guarantees we can check, such as exceptions in constructor calls used in emplace (the example from the rule text)." -AUTOSAR,A15-0-4,Yes,Required,Non-Automated,Architecture / Design / Implementation,Unchecked exceptions shall be used to represent errors from which the caller cannot reasonably be expected to recover.,,Exceptions1,Audit,Report a list of unchecked exceptions. -AUTOSAR,A15-0-5,Yes,Required,Non-Automated,Architecture / Design / Implementation,Checked exceptions shall be used to represent errors from which the caller can reasonably be expected to recover.,,Exceptions1,Audit,Report a list of checked exceptions. -AUTOSAR,A15-0-6,No,Required,Non-Automated,Verification / Toolchain,An analysis shall be performed to analyze the failure modes of exception,,,,Allocated target not covered by CodeQL -AUTOSAR,A15-0-7,No,Required,Partially Automated,Verification / Toolchain,Exception handling mechanism shall guarantee a deterministic worst-case time execution time.,,,,Allocated target not covered by CodeQL -AUTOSAR,A15-0-8,No,Required,Non-Automated,Verification / Toolchain,"A worst-case execution time (WCET) analysis shall be performed to determine maximum execution time constraints of the software, covering in particular the exceptions processing.",,,,Allocated target not covered by CodeQL -AUTOSAR,A15-1-1,Yes,Advisory,Automated,Implementation,Only instances of types derived from std::exception should be thrown.,,Exceptions2,Easy, -AUTOSAR,A15-1-2,Yes,Required,Automated,Implementation,An exception object shall not be a pointer.,,Exceptions1,Easy, -AUTOSAR,A15-1-3,Yes,Advisory,Automated,Implementation,All thrown exceptions should be unique.,,Exceptions1,Easy, -AUTOSAR,A15-1-4,Yes,Required,Partially Automated,Implementation,"If a function exits with an exception, then before a throw, the function shall place all objects/resources that the function constructed in valid states or it shall delete them.",ERR57-CPP,ExceptionSafety,Easy, -AUTOSAR,A15-1-5,Yes,Required,Non-Automated,Implementation,Exceptions shall not be thrown across execution boundaries.,ERR59-CPP,TrustBoundaries,Import,The database holds information about which compiler binary was used for each compilation. This can be used to identify execution boundaries between compilation units. -AUTOSAR,A15-2-1,Yes,Required,Automated,Implementation,Constructors that are not noexcept shall not be invoked before program startup.,ERR51-CPP,Exceptions1,Medium, -AUTOSAR,A15-2-2,Yes,Required,Partially Automated,Implementation,"If a constructor is not noexcept and the constructor cannot finish object initialization, then it shall deallocate the object's resources and it shall throw an exception.",ERR57-CPP,Exceptions2,Easy, -AUTOSAR,A15-3-2,No,Required,Non-Automated,Implementation,"If a function throws an exception, it shall be handled when meaningful actions can be taken, otherwise it shall be propagated.",,,,Difficult to identify when meaningful action could be taken. -AUTOSAR,A15-3-3,Yes,Required,Partially-Automated,Implementation,"Main function and a task main function shall catch at least: base class exceptions from all third-party libraries used, std::exception and all otherwise unhandled exceptions.",M15-3-2,Exceptions1,Easy, -AUTOSAR,A15-3-4,Yes,Required,Non-Automated,Implementation,"Catch-all (ellipsis and std::exception) handlers shall be used only in (a) main, (b) task main functions, (c) in functions that are supposed to isolate independent components and (d) when calling third-party code that uses exceptions not according to AUTOSAR C++14 guidelines.",,Exceptions1,Medium,"Identify catch-all handlers which aren't in main, aren't in functions called by std::thread or similar, and aren't wrapping external function calls. We may require some heuristics to exclude other ""isolation"" cases." -AUTOSAR,A15-3-5,Yes,Required,Automated,Implementation,A class type exception shall be caught by reference or const reference.,M15-3-5,Exceptions2,Easy, -AUTOSAR,A15-4-1,Yes,Required,Automated,Implementation,Dynamic exception-specification shall not be used.,,Exceptions1,Easy, -AUTOSAR,A15-4-2,Yes,Required,Automated,Implementation,"If a function is declared to be noexcept, noexcept(true) or noexcept(), then it shall not exit with an exception.",M15-5-2,Exceptions1,Medium, -AUTOSAR,A15-4-3,Yes,Required,Automated,Implementation,"The noexcept specification of a function shall either be identical across all translation units, or identical or more restrictive between a virtual member function and an overrider.",,Exceptions2,Easy, -AUTOSAR,A15-4-4,Yes,Required,Automated,Implementation,A declaration of non-throwing function shall contain noexcept specification.,,Exceptions1,Easy, -AUTOSAR,A15-4-5,Yes,Required,Automated,Implementation,Checked exceptions that could be thrown from a function shall be specified together with the function declaration and they shall be identical in all function declarations and for all its overriders.,,Exceptions2,Easy, -AUTOSAR,A15-5-1,Yes,Required,Automated,Implementation,"All user-provided class destructors, deallocation functions, move constructors, move assignment operators and swap functions shall not exit with an exception. A noexcept exception specification shall be added to these functions as appropriate.",M15-5-1,Exceptions2,Easy, -AUTOSAR,A15-5-2,Yes,Required,Partially Automated,Implementation,"Program shall not be abruptly terminated. In particular, an implicit or explicit invocation of std::abort(), std::quick_exit(), std::_Exit(), std::terminate() shall not be done.",ERR50-CPP,Exceptions1,Easy, -AUTOSAR,A15-5-3,Yes,Required,Automated,Implementation,The std::terminate() function shall not be called implicitly.,A15-5-2,Exceptions1,Medium, -AUTOSAR,A16-0-1,Yes,Required,Automated,Implementation,"The pre-processor shall only be used for unconditional and conditional file inclusion and include guards, and using the following directives: (1) #ifndef, #ifdef, (3) #if, (4) #if defined, (5) #elif, (6) #else, (7) #define, (8) #endif, (9) #include.",M16-2-1,Macros,Easy, -AUTOSAR,A16-2-1,Yes,Required,Automated,Implementation,"The ', "", /*, //, \ characters shall not occur in a header file name or in #include directive.",M16-2-4,Macros,Easy, -AUTOSAR,A16-2-2,Yes,Required,Automated,Implementation,There shall be no unused include directives.,cpp/dependency/useless-include,Includes,Hard,https://github.com/github/semmle-code/tree/main/packs/dependency/queries/semmlecode-cpp-queries/Dependency -AUTOSAR,A16-2-3,No,Required,Non-Automated,Implementation,An include directive shall be added explicitly for every symbol used in a file.,,,,There is no automated way to identify which headers are intended to be imported for each symbol. For the standard library we could scrape the documentation to determine which symbol is supposed to come from which header but the expected value is low. -AUTOSAR,A16-6-1,Yes,Required,Automated,Implementation,#error directive shall not be used.,,Macros,Easy, -AUTOSAR,A16-7-1,Yes,Required,Automated,Implementation,The #pragma directive shall not be used.,,Macros,Easy, -AUTOSAR,A17-0-1,Yes,Required,Automated,Implementation,"Reserved identifiers, macros and functions in the C++ standard library shall not be defined, redefined or undefined.",M17-0-1,BannedLibraries,Medium, -AUTOSAR,A17-0-2,No,Required,Non-Automated,Implementation,All project's code including used libraries (including standard and user-defined libraries) and any third-party user code shall conform to the AUTOSAR C++14 Coding Guidelines.,,,,"Self-referential. This is, in practice, covered by the rest of the queries, so I don't think we would have a specific query for this." -AUTOSAR,A17-1-1,Yes,Required,Non-Automated,Implementation,Use of the C Standard Library shall be encapsulated and isolated.,,Functions,Medium,Enforce that functions which call cstd functions are only calling cstd functions. -AUTOSAR,A17-6-1,Yes,Required,Automated,Implementation,Non-standard entities shall not be added to standard namespaces.,DCL58-CPP,Scope,Import, -AUTOSAR,A18-0-1,Yes,Required,Automated,Implementation,The C library facilities shall only be accessed through C++ library headers.,M18-0-1,BannedLibraries,Easy, -AUTOSAR,A18-0-2,Yes,Required,Automated,Implementation,The error state of a conversion from string to a numeric value shall be checked.,M18-0-2,TypeRanges,Medium, -AUTOSAR,A18-0-3,Yes,Required,Automated,Implementation,The library (locale.h) and the setlocale function shall not be used.,,BannedLibraries,Easy, -AUTOSAR,A18-1-1,Yes,Required,Automated,Implementation,C-style arrays shall not be used.,,BannedSyntax,Easy, -AUTOSAR,A18-1-2,Yes,Required,Automated,Implementation,The std::vector specialization shall not be used.,,BannedTypes,Easy, -AUTOSAR,A18-1-3,Yes,Required,Automated,Implementation,The std::auto_ptr type shall not be used.,,BannedTypes,Easy, -AUTOSAR,A18-1-4,Yes,Required,Automated,Implementation,A pointer pointing to an element of an array of objects shall not be passed to a smart pointer of single object type.,,Pointers,Medium, -AUTOSAR,A18-1-6,Yes,Required,Automated,Implementation,All std::hash specializations for user-defined types shall have a noexcept function call operator.,,OperatorInvariants,Easy, -AUTOSAR,A18-5-1,Yes,Required,Automated,Implementation,"Functions malloc, calloc, realloc and free shall not be used.",,BannedFunctions,Easy, -AUTOSAR,A18-5-10,Yes,Required,Automated,Implementation,Placement new shall be used only with properly aligned pointers to sufficient storage capacity.,MEM54-CPP,Allocations,Import, -AUTOSAR,A18-5-11,Yes,Required,Automated,Implementation,operator new' and 'operator delete' shall be defined together.,DCL54-CPP,Declarations,Easy, -AUTOSAR,A18-5-2,Yes,Required,Partially Automated,Implementation,Non-placement new or delete expressions shall not be used.,,Allocations,Hard, -AUTOSAR,A18-5-3,Yes,Required,Automated,Implementation,The form of the delete expression shall match the form of the new expression used to allocate the memory.,cpp/new-free-mismatch?,Freed,Very Hard, -AUTOSAR,A18-5-4,Yes,Required,Automated,Implementation,"If a project has sized or unsized version of operator 'delete' globally defined, then both sized and unsized versions shall be defined.",,Declarations,Easy, -AUTOSAR,A18-5-5,Yes,Required,Partially Automated,Toolchain,"Memory management functions shall ensure the following: (a) deterministic behavior resulting with the existence of worst-case execution time, (b) avoiding memory fragmentation, (c) avoid running out of memory, (d) 349 of 510 Document ID 839: AUTOSAR_RS_CPP14Guidelines",,Invariants,Hard, -AUTOSAR,A18-5-6,Yes,Required,Non-Automated,Verification / Toolchain,"An analysis shall be performed to analyze the failure modes of dynamic memory management. In particular, the following failure modes shall be analyzed: (a) non-deterministic behavior resulting with nonexistence of worst-case execution time, (b) memory fragmentation, (c) running out of memory, (d) mismatched allocations and deallocations, (e) dependence on non-deterministic calls to kernel.",,Allocations,Audit,Produce a list of allocations in the program. -AUTOSAR,A18-5-7,No,Required,Non-Automated,Implementation,"If non-realtime implementation of dynamic memory management functions is used in the project, then memory shall only be allocated and deallocated during non-realtime program phases.",,,,No specific ideas for implementing this. -AUTOSAR,A18-5-8,Yes,Required,Partially Automated,Implementation,Objects that do not outlive a function shall have automatic storage duration.,,Allocations,Medium, -AUTOSAR,A18-5-9,Yes,Required,Automated,Implementation,Custom implementations of dynamic memory allocation and deallocation functions shall meet the semantic requirements specified in the corresponding 'Required behaviour' clause from the C++ Standard.,MEM55-CPP,Allocations,Import, -AUTOSAR,A18-9-1,Yes,Required,Automated,Implementation,The std::bind shall not be used.,,BannedFunctions,Easy, -AUTOSAR,A18-9-2,Yes,Required,Automated,Implementation,"Forwarding values to other functions shall be done via: (1) std::move if the value is an rvalue reference, (2) std::forward if the value is forwarding reference.",,MoveForward,Medium, -AUTOSAR,A18-9-3,Yes,Required,Automated,Implementation,The std::move shall not be used on objects declared const or const&.,,MoveForward,Easy, -AUTOSAR,A18-9-4,Yes,Required,Automated,Implementation,An argument to std::forward shall not be subsequently used.,,MoveForward,Medium, -AUTOSAR,A2-10-1,Yes,Required,Automated,Architecture / Design / Implementation,An identifier declared in an inner scope shall not hide an identifier declared in an outer scope.,M2-10-2,Naming,Easy, -AUTOSAR,A2-10-4,Yes,Required,Automated,Implementation,The identifier name of a non-member object with static storage duration or static function shall not be reused within a namespace.,M2-10-5,Naming,Easy, -AUTOSAR,A2-10-5,Yes,Advisory,Automated,Design / Implementation,An identifier name of a function with static storage duration or a non-member object with external or internal linkage should not be reused.,M2-10-5,Naming,Easy, -AUTOSAR,A2-10-6,Yes,Required,Automated,Implementation,"A class or enumeration name shall not be hidden by a variable, function or enumerator declaration in the same scope.",M2-10-6,Naming,Easy, -AUTOSAR,A2-11-1,Yes,Required,Automated,Design / Implementation,Volatile keyword shall not be used.,cpp/jsf/av-rule-205,BannedSyntax,Easy, -AUTOSAR,A2-13-1,Yes,Required,Automated,Architecture / Design / Implementation,Only those escape sequences that are defined in ISO/IEC 14882:2014 shall be used.,M2-13-1,Literals,Easy, -AUTOSAR,A2-13-2,No,Required,Automated,Implementation,String literals with different encoding prefixes shall not be concatenated.,M2-13-5,,,"From the sample, it looks like this is compiler enforced." -AUTOSAR,A2-13-3,Yes,Required,Automated,Architecture / Design / Implementation,Type wchar_t shall not be used.,,BannedTypes,Easy, -AUTOSAR,A2-13-4,Yes,Required,Automated,Architecture / Design / Implementation,String literals shall not be assigned to non-constant pointers.,,Strings,Easy, -AUTOSAR,A2-13-5,Yes,Advisory,Automated,Implementation,Hexadecimal constants should be upper case.,,Literals,Easy, -AUTOSAR,A2-13-6,Yes,Required,Automated,Architecture / Design / Implementation,Universal character names shall be used only inside character or string literals.,,Naming,Easy, -AUTOSAR,A2-3-1,Yes,Required,Automated,Architecture / Design / Implementation,Only those characters specified in the C++ Language Standard basic source character set shall be used in the source code.,,Naming,Easy,"We can only provide partial coverage for this rule, because we have a semantic not syntactic model of the code." -AUTOSAR,A2-5-1,No,Required,Automated,Implementation,Trigraphs shall not be used.,,,,Trigraphs/digraphs are implemented by the preprocessor in a such a way that we may not have that information in our database. We could look for compiler flags here. -AUTOSAR,A2-5-2,No,Required,Automated,Implementation,Digraphs shall not be used.,,,,Trigraphs/digraphs are implemented by the preprocessor in a such a way that we may not have that information in our database. We could look for compiler flags here. -AUTOSAR,A2-7-1,Yes,Required,Automated,Implementation,The character \ shall not occur as a last character of a C++ comment.,,Comments,Easy, -AUTOSAR,A2-7-2,Yes,Required,Non-Automated,Implementation,Sections of code shall not be 'commented out'.,M2-7-2,Comments,Easy,We can write a heuristic query that looks for code markers in comments. -AUTOSAR,A2-7-3,Yes,Required,Automated,Implementation,"All declarations of 'user-defined' types, static and non-static data members, functions and methods shall be preceded by documentation.",,Comments,Easy, -AUTOSAR,A2-7-5,No,Required,Non-Automated,Implementation,"Comments shall not document any actions or sources (e.g. tables, figures, paragraphs, etc.) that are outside of the file.",,,,Difficult to ascertain programmatically -AUTOSAR,A2-8-1,No,Required,Non-Automated,Architecture / Design / Implementation,A header file name should reflect the logical entity for which it provides declarations.,,,,Difficult to ascertain programmatically -AUTOSAR,A2-8-2,No,Advisory,Non-Automated,Architecture / Design / Implementation,An implementation file name should reflect the logical entity for which it provides definitions.,,,,Difficult to ascertain programmatically -AUTOSAR,A20-8-1,Yes,Required,Automated,Implementation,An already-owned pointer value shall not be stored in an unrelated smart pointer.,MEM56-CPP,SmartPointers1,Import, -AUTOSAR,A20-8-2,Yes,Required,Automated,Implementation,A std::unique_ptr shall be used to represent exclusive ownership.,,SmartPointers1,Hard, -AUTOSAR,A20-8-3,Yes,Required,Automated,Implementation,A std::shared_ptr shall be used to represent shared ownership.,,SmartPointers1,Hard, -AUTOSAR,A20-8-4,Yes,Required,Automated,Implementation,A std::unique_ptr shall be used over std::shared_ptr if ownership sharing is not required.,,SmartPointers1,Hard, -AUTOSAR,A20-8-5,Yes,Required,Automated,Implementation,std::make_unique shall be used to construct objects owned by std::unique_ptr.,,SmartPointers1,Easy, -AUTOSAR,A20-8-6,Yes,Required,Automated,Implementation,std::make_shared shall be used to construct objects owned by std::shared_ptr.,,SmartPointers1,Easy, -AUTOSAR,A20-8-7,Yes,Required,Non-Automated,Implementation,A std::weak_ptr shall be used to represent temporary shared ownership.,,SmartPointers2,Hard,"We can find some specific cases here: mutual assignment of two variables, for example." -AUTOSAR,A21-8-1,Yes,Required,Automated,Implementation,Arguments to character-handling functions shall be representable as an unsigned char.,STR37-C,TypeRanges,Hard, -AUTOSAR,A23-0-1,Yes,Required,Automated,Implementation,An iterator shall not be implicitly converted to const_iterator.,,Iterators,Easy, -AUTOSAR,A23-0-2,Yes,Required,Automated,Implementation,"Elements of a container shall only be accessed via valid references, iterators, and pointers.",CTR51-CPP,Iterators,Import, -AUTOSAR,A25-1-1,Yes,Required,Automated,Implementation,Non-static data members or captured values of predicate function objects that are state related to this object's identity shall not be copied.,CTR58-CPP,SideEffects2,Import, -AUTOSAR,A25-4-1,Yes,Required,Non-Automated,Implementation,Ordering predicates used with associative containers and STL sorting and related algorithms shall adhere to a strict weak ordering relation.,CTR57-CPP,Invariants,Import,Hard to determine in general. Easiest is likely the irreflexivity clause (specifically using std::less_equal and similar library functions) -AUTOSAR,A26-5-1,Yes,Required,Automated,Implementation,Pseudorandom numbers shall not be generated using std::rand().,MSC50-CPP,BannedFunctions,Import, -AUTOSAR,A26-5-2,Yes,Required,Automated,Implementation,Random number engines shall not be default-initialized.,MSC51-CPP,Initialization,Easy, -AUTOSAR,A27-0-1,Yes,Required,Non-Automated,Implementation,Inputs from independent components shall be validated.,,TypeRanges,Medium,"We can perform some checking here assuming: we have annotations which determine the boundaries between components, and the appropriate checks that should be performed." -AUTOSAR,A27-0-2,Yes,Advisory,Automated,Implementation,A C-style string shall guarantee sufficient space for data and the null terminator.,STR50-CPP,Strings,Import, -AUTOSAR,A27-0-3,Yes,Required,Automated,Implementation,Alternate input and output operations on a file stream shall not be used without an intervening flush or positioning call.,FIO50-CPP,IO,Import, -AUTOSAR,A27-0-4,Yes,Required,Automated,Implementation,C-style strings shall not be used.,,Strings,Hard, -AUTOSAR,A3-1-1,Yes,Required,Automated,Architecture / Design / Implementation,It shall be possible to include any header file in multiple translation units without violating the One Definition Rule.,M3-1-1,Includes,Easy, -AUTOSAR,A3-1-2,Yes,Required,Automated,Architecture / Design / Implementation,"Header files, that are defined locally in the project, shall have a file name extension of one of: "".h"", "".hpp"" or "".hxx"".",cpp/jsf/av-rule-53,Includes,Easy, -AUTOSAR,A3-1-3,Yes,Advisory,Automated,Architecture / Design / Implementation,"Implementation files, that are defined locally in the project, should have a file name extension of "".cpp"".",,Includes,Easy, -AUTOSAR,A3-1-4,Yes,Required,Automated,Design / Implementation,"When an array with external linkage is declared, its size shall be stated explicitly.",M3-1-3,Scope,Easy, -AUTOSAR,A3-1-5,Yes,Required,Partially-Automated,Design,A function definition shall only be placed in a class definition if (1) the function is intended to be inlined (2) it is a member function template (3) it is a member function of a class template.,,Classes,Medium, -AUTOSAR,A3-1-6,Yes,Advisory,Automated,Design,Trivial accessor and mutator functions should be inlined.,,Functions,Easy, -AUTOSAR,A3-3-1,Yes,Required,Automated,Implementation,Objects or functions with external linkage (including members of named namespaces) shall be declared in a header file.,M3-3-1,Includes,Easy, -AUTOSAR,A3-3-2,Yes,Required,Automated,Implementation,Static and thread-local objects shall be constant-initialized.,DCL56-CPP,Initialization,Medium, -AUTOSAR,A3-8-1,Yes,Required,Non-Automated,Implementation,An object shall not be accessed outside of its lifetime.,EXP54-CPP,Freed,Import,"A replica of a CERT-CPP rule, there are numerous specific cases we can cover." -AUTOSAR,A3-9-1,Yes,Required,Automated,Implementation,"Fixed width integer types from , indicating the size and signedness, shall be used in place of the basic numerical types.",M3-9-2,Declarations,Easy, -AUTOSAR,A4-10-1,Yes,Required,Automated,Architecture / Design / Implementation,Only nullptr literal shall be used as the null-pointer-constant.,,Literals,Easy, -AUTOSAR,A4-5-1,Yes,Required,Automated,Implementation,"Expressions with type enum or enum class shall not be used as operands to built-in and overloaded operators other than the subscript operator [ ], the assignment operator =, the equality operators == and ! =, the unary & operator, and the relational operators <, <=, >, >=.",M4-5-2,Expressions,Easy, -AUTOSAR,A4-7-1,Yes,Required,Automated,Implementation,An integer expression shall not lead to data loss.,M5-0-6,IntegerConversion,Very Hard, -AUTOSAR,A5-0-1,Yes,Required,Automated,Implementation,The value of an expression shall be the same under any order of evaluation that the standard permits.,M5-0-1,OrderOfEvaluation,Hard, -AUTOSAR,A5-0-2,Yes,Required,Automated,Implementation,The condition of an if-statement and the condition of an iteration statement shall have type bool.,M5-0-13,Conditionals,Easy, -AUTOSAR,A5-0-3,Yes,Required,Automated,Implementation,The declaration of objects shall contain no more than two levels of pointer indirection.,M5-0-19,Pointers,Easy, -AUTOSAR,A5-0-4,Yes,Required,Automated,Implementation,Pointer arithmetic shall not be used with pointers to non-final classes.,CTR56-CPP,Pointers,Easy, -AUTOSAR,A5-1-1,Yes,Required,Partially Automated,Implementation,"Literal values shall not be used apart from type initialization, otherwise symbolic names shall be used instead.",,Literals,Easy, -AUTOSAR,A5-1-2,Yes,Required,Automated,Implementation,Variables shall not be implicitly captured in a lambda expression.,,Lambdas,Easy, -AUTOSAR,A5-1-3,Yes,Required,Automated,Implementation,Parameter list (possibly empty) shall be included in every lambda expression.,,Lambdas,Easy, -AUTOSAR,A5-1-4,Yes,Required,Automated,Implementation,A lambda expression object shall not outlive any of its reference-captured objects.,EXP61-CPP,Lambdas,Import, -AUTOSAR,A5-1-6,Yes,Advisory,Automated,Implementation,Return type of a non-void return type lambda expression should be explicitly specified.,,Lambdas,Easy, -AUTOSAR,A5-1-7,Yes,Required,Automated,Implementation,A lambda shall not be an operand to decltype or typeid.,,Lambdas,Easy, -AUTOSAR,A5-1-8,Yes,Advisory,Automated,Implementation,Lambda expressions should not be defined inside another lambda expression.,,Lambdas,Easy, -AUTOSAR,A5-1-9,Yes,Advisory,Automated,Implementation,Identical unnamed lambda expressions shall be replaced with a named function or a named lambda expression.,,Lambdas,Very Hard, -AUTOSAR,A5-10-1,Yes,Required,Automated,Implementation,A pointer to member virtual function shall only be tested for equality with null-pointer-constant.,,Pointers,Medium, -AUTOSAR,A5-16-1,Yes,Required,Automated,Implementation,The ternary conditional operator shall not be used as a sub-expression.,,BannedSyntax,Easy, -AUTOSAR,A5-2-1,Yes,Advisory,Automated,Implementation,dynamic_cast should not be used.,,BannedSyntax,Easy, -AUTOSAR,A5-2-2,Yes,Required,Automated,Implementation,Traditional C-style casts shall not be used.,,BannedSyntax,Easy, -AUTOSAR,A5-2-3,Yes,Required,Automated,Implementation,A cast shall not remove any const or volatile qualification from the type of a pointer or reference.,EXP55-CPP,Const,Import, -AUTOSAR,A5-2-4,Yes,Required,Automated,Implementation,reinterpret_cast shall not be used.,M5-2-7,BannedSyntax,Easy, -AUTOSAR,A5-2-5,Yes,Required,Automated,Implementation,An array or container shall not be accessed beyond its range.,CTR50-CPP,OutOfBounds,Import, -AUTOSAR,A5-2-6,Yes,Required,Automated,Implementation,The operands of a logical && or || shall be parenthesized if the operands contain binary operators.,M5-2-1,OrderOfEvaluation,Easy, -AUTOSAR,A5-3-1,Yes,Required,Non-Automated,Implementation,Evaluation of the operand to the typeid operator shall not contain side effects.,,SideEffects1,Easy,"We will make use of a shared ""side-effects"" library for this query." -AUTOSAR,A5-3-2,Yes,Required,Partially Automated,Implementation,Null pointers shall not be dereferenced.,,Null,Very Hard, -AUTOSAR,A5-3-3,Yes,Required,Automated,Implementation,Pointers to incomplete class types shall not be deleted.,EXP57-CPP,Pointers,Easy, -AUTOSAR,A5-5-1,Yes,Required,Automated,Implementation,A pointer to member shall not access non-existent class members.,OOP55-CPP,Pointers,Import, -AUTOSAR,A5-6-1,Yes,Required,Automated,Implementation,The right hand operand of the integer division or remainder operators shall not be equal to zero.,,Expressions,Hard, -AUTOSAR,A6-2-1,Yes,Required,Automated,Implementation,"Move and copy assignment operators shall either move or respectively copy base classes and data members of a class, without any side effects.",,SideEffects2,Hard, -AUTOSAR,A6-2-2,Yes,Required,Automated,Implementation,Expression statements shall not be explicit calls to constructors of temporary objects only.,,OrderOfEvaluation,Easy, -AUTOSAR,A6-4-1,Yes,Required,Automated,Implementation,"A switch statement shall have at least two case-clauses, distinct from the default label.",cpp/trivial-switch,Conditionals,Easy, -AUTOSAR,A6-5-1,Yes,Required,Automated,Implementation,A for-loop that loops through all elements of the container and does not use its loop-counter shall not be used.,,Loops,Easy, -AUTOSAR,A6-5-2,Yes,Required,Automated,Implementation,A for loop shall contain a single loop-counter which shall not have floating-point type.,M6-5-1,Loops,Easy, -AUTOSAR,A6-5-3,Yes,Advisory,Automated,Implementation,Do statements should not be used.,,Loops,Easy, -AUTOSAR,A6-5-4,Yes,Advisory,Automated,Implementation,For-init-statement and expression should not perform actions other than loop-counter initialization and modification.,,Loops,Easy, -AUTOSAR,A6-6-1,Yes,Required,Automated,Implementation,The goto statement shall not be used.,cpp/jpl-c/simple-control-flow-goto,BannedSyntax,Easy, -AUTOSAR,A7-1-1,Yes,Required,Automated,Implementation,Constexpr or const specifiers shall be used for immutable data declaration.,,Const,Hard, -AUTOSAR,A7-1-2,Yes,Required,Automated,Implementation,The constexpr specifier shall be used for values that can be determined at compile time.,,Const,Medium, -AUTOSAR,A7-1-3,Yes,Required,Automated,Implementation,CV-qualifiers shall be placed on the right hand side of the type that is a typedef or a using name.,,Const,Easy, -AUTOSAR,A7-1-4,Yes,Required,Automated,Implementation,The register keyword shall not be used.,,BannedSyntax,Easy, -AUTOSAR,A7-1-5,Yes,Required,Automated,Implementation,"The auto specifier shall not be used apart from following cases: (1) to declare that a variable has the same type as return type of a function call, (2) to declare that a variable has the same type as initializer of non-fundamental type, (3) to declare parameters of a generic lambda expression, (4) to declare a function template using trailing return type syntax.",,Declarations,Medium, -AUTOSAR,A7-1-6,Yes,Required,Automated,Implementation,The typedef specifier shall not be used.,,BannedSyntax,Easy, -AUTOSAR,A7-1-7,Yes,Required,Automated,Implementation,Each expression statement and identifier declaration shall be placed on a separate line.,,Declarations,Easy, -AUTOSAR,A7-1-8,Yes,Required,Automated,Implementation,A non-type specifier shall be placed before a type specifier in a declaration.,,Declarations,Easy, -AUTOSAR,A7-1-9,Yes,Required,Automated,Implementation,"A class, structure, or enumeration shall not be declared in the definition of its type.",,Declarations,Easy, -AUTOSAR,A7-2-1,Yes,Required,Automated,Implementation,An expression with enum underlying type shall only have values corresponding to the enumerators of the enumeration.,M7-2-1,TypeRanges,Hard, -AUTOSAR,A7-2-2,Yes,Required,Automated,Implementation,Enumeration underlying base type shall be explicitly defined.,,Declarations,Easy, -AUTOSAR,A7-2-3,Yes,Required,Automated,Implementation,Enumerations shall be declared as scoped enum classes.,,Declarations,Easy, -AUTOSAR,A7-2-4,Yes,Required,Automated,Implementation,"In an enumeration, either (1) none, (2) the first or (3) all enumerators shall be initialized.",M8-5-3,Declarations,Easy, -AUTOSAR,A7-2-5,Yes,Advisory,Non-Automated,Design,Enumerations should be used to represent sets of related named constants.,,TypeRanges,Audit,List all enumerations -AUTOSAR,A7-3-1,Yes,Required,Automated,Implementation,All overloads of a function shall be visible from where it is called.,M7-3-5,Scope,Easy, -AUTOSAR,A7-4-1,Yes,Required,Automated,Implementation,The asm declaration shall not be used.,,BannedSyntax,Easy, -AUTOSAR,A7-5-1,Yes,Required,Automated,Implementation,A function shall not return a reference or a pointer to a parameter that is passed by reference to const.,,Functions,Easy, -AUTOSAR,A7-5-2,Yes,Required,Automated,Implementation,"Functions shall not call themselves, either directly or indirectly.",M7-5-4,Functions,Easy, -AUTOSAR,A7-6-1,Yes,Required,Automated,Implementation,Functions declared with the [[noreturn]] attribute shall not return.,MSC53-CPP,Functions,Import, -AUTOSAR,A8-2-1,Yes,Required,Automated,Implementation,"When declaring function templates, the trailing return type syntax shall be used if the return type depends on the type of parameters.",,Templates,Easy, -AUTOSAR,A8-4-1,Yes,Required,Automated,Implementation,Functions shall not be defined using the ellipsis notation.,M8-4-1,BannedSyntax,Easy, -AUTOSAR,A8-4-10,Yes,Required,Automated,Design,A parameter shall be passed by reference if it can't be NULL,,Null,Hard, -AUTOSAR,A8-4-11,Yes,Required,Automated,Design,A smart pointer shall only be used as a parameter type if it expresses lifetime semantics,,SmartPointers1,Medium, -AUTOSAR,A8-4-12,Yes,Required,Automated,Design,A std::unique_ptr shall be passed to a function as: (1) a copy to express the function assumes ownership (2) an lvalue reference to express that the function replaces the managed object.,,SmartPointers1,Medium, -AUTOSAR,A8-4-13,Yes,Required,Automated,Design,A std::shared_ptr shall be passed to a function as: (1) a copy to express the function shares ownership (2) an lvalue reference to express that the function replaces the managed object (3) a const lvalue reference to express that the function retains a reference count.,,SmartPointers1,Medium, -AUTOSAR,A8-4-14,No,Required,Non-Automated,Design,Interfaces shall be precisely and strongly typed.,,,,Difficult to ascertain programmatically -AUTOSAR,A8-4-2,Yes,Required,Automated,Implementation,All exit paths from a function with non-void return type shall have an explicit return statement with an expression.,M8-4-3,Functions,Easy, -AUTOSAR,A8-4-3,No,Advisory,Non-Automated,Design,Common ways of passing parameters should be used.,,,,The practical parts of this are covered by other rules (such as A8-4-5 to A8-4-9) -AUTOSAR,A8-4-4,Yes,Advisory,Automated,Design,Multiple output values from a function should be returned as a struct or tuple.,,Functions,Easy, -AUTOSAR,A8-4-5,Yes,Required,Automated,Design,"'consume' parameters declared as X && shall always be moved from.",,MoveForward,Easy, -AUTOSAR,A8-4-6,Yes,Required,Automated,Design,"'forward' parameters declared as T && shall always be forwarded.",,MoveForward,Easy, -AUTOSAR,A8-4-7,Yes,Required,Automated,Design,"'in' parameters for 'cheap to copy' types shall be passed by value.",,Classes,Easy, -AUTOSAR,A8-4-8,Yes,Required,Automated,Design,Output parameters shall not be used.,,Const,Easy, -AUTOSAR,A8-4-9,Yes,Required,Automated,Design,"'in-out' parameters declared as T & shall be modified.",,Const,Medium, -AUTOSAR,A8-5-0,Yes,Required,Automated,Implementation,All memory shall be initialized before it is read.,M8-5-1,Uninitialized,Very Hard, -AUTOSAR,A8-5-1,Yes,Required,Automated,Implementation,"In an initialization list, the order of initialization shall be following: (1) virtual base classes in depth and left to right order of the inheritance graph, (2) direct base classes in left to right order of inheritance list, (3) non-static data members in the order they were declared in the class definition.",,Initialization,Easy, -AUTOSAR,A8-5-2,Yes,Required,Automated,Implementation,"Braced-initialization {}, without equals sign, shall be used for variable initialization.",,Initialization,Easy, -AUTOSAR,A8-5-3,Yes,Required,Automated,Implementation,A variable of type auto shall not be initialized using {} or ={} braced-initialization.,,Initialization,Easy, -AUTOSAR,A8-5-4,Yes,Advisory,Automated,Implementation,"If a class has a user-declared constructor that takes a parameter of type std::initializer_list, then it shall be the only constructor apart from special member function constructors.",,Initialization,Easy, -AUTOSAR,A9-3-1,Yes,Required,Partially Automated,Implementation,Member functions shall not return non-const 'raw' pointers or references to private or protected data owned by the class.,M9-3-2,Classes,Hard, -AUTOSAR,A9-5-1,Yes,Required,Automated,Implementation,Unions shall not be used.,M9-5-1,BannedSyntax,Easy, -AUTOSAR,A9-6-1,Yes,Required,Partially Automated,Design,"Data types used for interfacing with hardware or conforming to communication protocols shall be trivial, standard-layout and only contain members of types with defined sizes.",,Classes,Medium, -AUTOSAR,A9-6-2,Yes,Required,Non-Automated,Design,Bit-fields shall be used only when interfacing to hardware or conforming to communication protocols.,,Representation,Audit,Produce an audit list. Omit items from the audit list which have an appropriate annotation. -AUTOSAR,M0-1-1,Yes,Required,Automated,Implementation,A project shall not contain unreachable code.,cpp/jsf/av-rule-186,DeadCode,Easy, -AUTOSAR,M0-1-10,Yes,Advisory,Automated,Implementation,Every defined function should be called at least once.,cpp/unused-static-function,DeadCode,Easy, -AUTOSAR,M0-1-2,Yes,Required,Automated,Implementation,A project shall not contain infeasible paths.,,DeadCode,Very Hard, -AUTOSAR,M0-1-3,Yes,Required,Automated,Implementation,A project shall not contain unused variables.,cpp/unused-static-variable and ,DeadCode,Easy, -AUTOSAR,M0-1-4,Yes,Required,Automated,Implementation,A project shall not contain non-volatile POD variables having only one use.,,DeadCode,Easy, -AUTOSAR,M0-1-8,Yes,Required,Automated,Implementation,All functions with void return type shall have external side effect(s).,,SideEffects2,Medium, -AUTOSAR,M0-1-9,Yes,Required,Automated,Implementation,There shall be no dead code.,cpp/dead-code-condition???,DeadCode,Medium, -AUTOSAR,M0-2-1,Yes,Required,Automated,Implementation,An object shall not be assigned to an overlapping object.,,Representation,Hard, -AUTOSAR,M0-3-1,No,Required,Non-Automated,Implementation / Verification,Minimization of run-time failures shall be ensured by the use of at least one of: (a) static analysis tools/techniques; (b) dynamic analysis tools/techniques; (c) explicit coding of checks to handle run-time faults.,,,,Allocated target not covered by CodeQL -AUTOSAR,M0-3-2,Yes,Required,Non-Automated,Implementation,"If a function generates error information, then that error information shall be tested.",cpp/jpl-c/checking-return-values???,Expressions,Medium,"We can identify certain common error cases (return value, return parameter, global parameter) and confirm they have been checked." -AUTOSAR,M0-4-1,No,Required,Non-Automated,Implementation,Use of scaled-integer or fixed-point arithmetic shall be documented.,,,,Documentation not covered by queries -AUTOSAR,M0-4-2,No,Required,Non-Automated,Implementation,Use of floating-point arithmetic shall be documented.,,,,Documentation not covered by queries -AUTOSAR,M1-0-2,No,Required,Non-Automated,Toolchain,"Multiple compilers shall only be used if they have a common, defined interface.",,,,Allocated target not covered by CodeQL -AUTOSAR,M10-1-1,Yes,Advisory,Automated,Implementation,Classes should not be derived from virtual bases.,,Inheritance,Easy, -AUTOSAR,M10-1-2,Yes,Required,Automated,Implementation,A base class shall only be declared virtual if it is used in a diamond hierarchy.,,Inheritance,Easy, -AUTOSAR,M10-1-3,Yes,Required,Automated,Implementation,An accessible base class shall not be both virtual and non-virtual in the same hierarchy.,,Inheritance,Easy, -AUTOSAR,M10-2-1,Yes,Advisory,Automated,Implementation,All accessible entity names within a multiple inheritance hierarchy should be unique.,,Inheritance,Easy, -AUTOSAR,M10-3-3,Yes,Required,Automated,Implementation,A virtual function shall only be overridden by a pure virtual function if it is itself declared as pure virtual.,,VirtualFunctions,Easy, -AUTOSAR,M11-0-1,Yes,Required,Automated,Implementation,Member data in non-POD class types shall be private.,,Classes,Easy, -AUTOSAR,M12-1-1,Yes,Required,Automated,Implementation,An object's dynamic type shall not be used from the body of its constructor or destructor.,,Inheritance,Easy, -AUTOSAR,M14-5-3,Yes,Required,Automated,Implementation,A copy assignment operator shall be declared when there is a template assignment operator with a parameter that is a generic parameter.,,Templates,Easy, -AUTOSAR,M14-6-1,Yes,Required,Automated,Implementation,"In a class template with a dependent base, any name that may be found in that dependent base shall be referred to using a qualified-id or this->.",,Templates,Easy, -AUTOSAR,M15-0-3,Yes,Required,Automated,Implementation,Control shall not be transferred into a try or catch block using a goto or a switch statement.,,Exceptions1,Easy, -AUTOSAR,M15-1-1,Yes,Required,Automated,Implementation,The assignment-expression of a throw statement shall not itself cause an exception to be thrown.,,Exceptions1,Easy, -AUTOSAR,M15-1-2,Yes,Required,Automated,Implementation,NULL shall not be thrown explicitly.,,Exceptions1,Easy, -AUTOSAR,M15-1-3,Yes,Required,Automated,Implementation,An empty throw (throw;) shall only be used in the compound statement of a catch handler.,,Exceptions1,Easy, -AUTOSAR,M15-3-1,Yes,Required,Automated,Implementation,Exceptions shall be raised only after start-up and before termination.,,Exceptions2,Easy, -AUTOSAR,M15-3-3,Yes,Required,Automated,Implementation,Handlers of a function-try-block implementation of a class constructor or destructor shall not reference non-static members from this class or its bases.,ERR53-CPP,Exceptions2,Import, -AUTOSAR,M15-3-4,Yes,Required,Automated,Implementation,Each exception explicitly thrown in the code shall have a handler of a compatible type in all call paths that could lead to that point.,,Exceptions1,Medium, -AUTOSAR,M15-3-6,Yes,Required,Automated,Implementation,"Where multiple handlers are provided in a single try-catch statement or function-try-block for a derived class and some or all of its bases, the handlers shall be ordered most-derived to base class.",ERR54-CPP,Exceptions2,Import, -AUTOSAR,M15-3-7,Yes,Required,Automated,Implementation,"Where multiple handlers are provided in a single try-catch statement or function-try-block, any ellipsis (catch-all) handler shall occur last.",,Exceptions1,Easy, -AUTOSAR,M16-0-1,Yes,Required,Automated,Implementation,#include directives in a file shall only be preceded by other pre-processor directives or comments.,cpp/jpl-c/includes-first,Macros,Easy, -AUTOSAR,M16-0-2,Yes,Required,Automated,Implementation,Macros shall only be #define'd or #undef'd in the global namespace.,,Macros,Easy, -AUTOSAR,M16-0-5,Yes,Required,Automated,Implementation,Arguments to a function-like macro shall not contain tokens that look like pre-processing directives.,,Macros,Easy, -AUTOSAR,M16-0-6,Yes,Required,Automated,Implementation,"In the definition of a function-like macro, each instance of a parameter shall be enclosed in parentheses, unless it is used as the operand of # or ##.",,Macros,Easy, -AUTOSAR,M16-0-7,Yes,Required,Automated,Implementation,"Undefined macro identifiers shall not be used in #if or #elif pre-processor directives, except as operands to the defined operator.",,Macros,Hard, -AUTOSAR,M16-0-8,No,Required,Automated,Implementation,"If the # token appears as the first token on a line, then it shall be immediately followed by a pre-processing token.",,,,This is verified by the compiler in the cases where the token is not within an ifdef branch that's never taken -AUTOSAR,M16-1-1,Yes,Required,Automated,Implementation,The defined pre-processor operator shall only be used in one of the two standard forms.,,Macros,Easy, -AUTOSAR,M16-1-2,No,Required,Automated,Implementation,"All #else, #elif and #endif pre-processor directives shall reside in the same file as the #if or #ifdef directive to which they are related.",,,,Compilers already prohibit this case -AUTOSAR,M16-2-3,Yes,Required,Automated,Implementation,Include guards shall be provided.,cpp/missing-header-guard,Includes,Easy, -AUTOSAR,M16-3-1,Yes,Required,Automated,Implementation,There shall be at most one occurrence of the # or ## operators in a single macro definition.,,Macros,Easy, -AUTOSAR,M16-3-2,Yes,Advisory,Automated,Implementation,The # and ## operators should not be used.,,Macros,Easy, -AUTOSAR,M17-0-2,Yes,Required,Automated,Implementation,The names of standard library macros and objects shall not be reused.,,Naming,Medium, -AUTOSAR,M17-0-3,Yes,Required,Automated,Implementation,The names of standard library functions shall not be overridden.,,Naming,Medium, -AUTOSAR,M17-0-5,Yes,Required,Automated,Implementation,The setjmp macro and the longjmp function shall not be used.,ERR52-CPP,BannedFunctions,Import, -AUTOSAR,M18-0-3,Yes,Required,Automated,Implementation,"The library functions abort, exit, getenv and system from library shall not be used.",,BannedFunctions,Easy, -AUTOSAR,M18-0-4,Yes,Required,Automated,Implementation,The time handling functions of library shall not be used.,,BannedFunctions,Easy, -AUTOSAR,M18-0-5,Yes,Required,Automated,Implementation,The unbounded functions of library shall not be used.,,BannedFunctions,Easy, -AUTOSAR,M18-2-1,Yes,Required,Automated,Implementation,The macro offsetof shall not be used.,,BannedFunctions,Easy, -AUTOSAR,M18-7-1,Yes,Required,Automated,Implementation,The signal handling facilities of shall not be used.,,BannedLibraries,Easy, -AUTOSAR,M19-3-1,Yes,Required,Automated,Implementation,The error indicator errno shall not be used.,,BannedLibraries,Easy, -AUTOSAR,M2-10-1,Yes,Required,Automated,Architecture / Design / Implementation,Different identifiers shall be typographically unambiguous.,,Naming,Easy, -AUTOSAR,M2-13-2,Yes,Required,Automated,Architecture / Design / Implementation,Octal constants (other than zero) and octal escape sequences (other than '\0' ) shall not be used.,,Literals,Easy, -AUTOSAR,M2-13-3,Yes,Required,Automated,Architecture / Design / Implementation,A 'U' suffix shall be applied to all octal or hexadecimal integer literals of unsigned type.,,Literals,Easy, -AUTOSAR,M2-13-4,Yes,Required,Automated,Architecture / Design / Implementation,Literal suffixes shall be upper case.,,Literals,Easy, -AUTOSAR,M2-7-1,Yes,Required,Automated,Implementation,The character sequence /* shall not be used within a C-style comment.,,Comments,Easy, -AUTOSAR,M27-0-1,Yes,Required,Automated,Implementation,The stream input/output library shall not be used.,,BannedLibraries,Easy, -AUTOSAR,M3-1-2,Yes,Required,Automated,Implementation,Functions shall not be declared at block scope.,,Declarations,Easy, -AUTOSAR,M3-2-1,Yes,Required,Automated,Implementation,All declarations of an object or function shall have compatible types.,,Declarations,Easy, -AUTOSAR,M3-2-2,Yes,Required,Automated,Implementation,The One Definition Rule shall not be violated.,DCL60-CPP,Scope,Import, -AUTOSAR,M3-2-3,Yes,Required,Automated,Implementation,"A type, object or function that is used in multiple translation units shall be declared in one and only one file.",,Scope,Easy, -AUTOSAR,M3-2-4,Yes,Required,Automated,Implementation,An identifier with external linkage shall have exactly one definition.,,Scope,Easy, -AUTOSAR,M3-3-2,Yes,Required,Automated,Implementation,If a function has internal linkage then all re-declarations shall include the static storage class specifier.,,Scope,Easy, -AUTOSAR,M3-4-1,Yes,Required,Automated,Implementation,An identifier declared to be an object or type shall be defined in a block that minimizes its visibility.,,Scope,Easy, -AUTOSAR,M3-9-1,Yes,Required,Automated,Implementation,"The types used for an object, a function return type, or a function parameter shall be token-for-token identical in all declarations and re-declarations.",M8-4-2,Declarations,Easy, -AUTOSAR,M3-9-3,Yes,Required,Automated,Implementation,The underlying bit representations of floating-point values shall not be used.,,Representation,Easy, -AUTOSAR,M4-10-1,Yes,Required,Automated,Implementation,NULL shall not be used as an integer value.,,Literals,Easy, -AUTOSAR,M4-10-2,Yes,Required,Automated,Implementation,Literal zero (0) shall not be used as the null-pointer-constant.,A4-10-1,Literals,Easy, -AUTOSAR,M4-5-1,Yes,Required,Automated,Implementation,"Expressions with type bool shall not be used as operands to built-in operators other than the assignment operator =, the logical operators",,Expressions,Easy, -AUTOSAR,M4-5-3,Yes,Required,Automated,Implementation,"Expressions with type (plain) char and wchar_t shall not be used as operands to built-in operators other than the assignment operator =, the equality operators == and ! =, and the unary & operator.",,Expressions,Easy, -AUTOSAR,M5-0-10,Yes,Required,Automated,Implementation,"If the bitwise operators ~and << are applied to an operand with an underlying type of unsigned char or unsigned short, the result shall be immediately cast to the underlying type of the operand.",,Operators,Easy, -AUTOSAR,M5-0-11,Yes,Required,Automated,Implementation,The plain char type shall only be used for the storage and use of character values.,CMISRA-6-01,Strings,Easy, -AUTOSAR,M5-0-12,Yes,Required,Automated,Implementation,Signed char and unsigned char type shall only be used for the storage and use of numeric values.,CMISRA-6-02,Strings,Easy, -AUTOSAR,M5-0-14,Yes,Required,Automated,Implementation,The first operand of a conditional-operator shall have type bool.,,Expressions,Easy, -AUTOSAR,M5-0-15,Yes,Required,Automated,Implementation,Array indexing shall be the only form of pointer arithmetic.,cpp/jsf/av-rule-215?,Pointers,Easy, -AUTOSAR,M5-0-16,Yes,Required,Automated,Implementation,A pointer operand and any pointer resulting from pointer arithmetic using that operand shall both address elements of the same array.,CTR50-CPP,Pointers,Hard, -AUTOSAR,M5-0-17,Yes,Required,Automated,Implementation,Subtraction between pointers shall only be applied to pointers that address elements of the same array.,,Pointers,Easy, -AUTOSAR,M5-0-18,Yes,Required,Automated,Implementation,">, >=, <, <= shall not be applied to objects of pointer type, except where they point to the same array.",,Pointers,Easy, -AUTOSAR,M5-0-2,Yes,Advisory,Partially Automated,Implementation,Limited dependence should be placed on C++ operator precedence rules in expressions.,,OrderOfEvaluation,Easy, -AUTOSAR,M5-0-20,Yes,Required,Automated,Implementation,Non-constant operands to a binary bitwise operator shall have the same underlying type.,,Expressions,Easy, -AUTOSAR,M5-0-21,Yes,Required,Automated,Implementation,Bitwise operators shall only be applied to operands of unsigned underlying type.,,Expressions,Easy, -AUTOSAR,M5-0-3,Yes,Required,Automated,Implementation,A cvalue expression shall not be implicitly converted to a different underlying type.,,Expressions,Easy, -AUTOSAR,M5-0-4,Yes,Required,Automated,Implementation,An implicit integral conversion shall not change the signedness of the underlying type.,,IntegerConversion,Easy, -AUTOSAR,M5-0-5,Yes,Required,Automated,Implementation,There shall be no implicit floating-integral conversions.,,IntegerConversion,Easy, -AUTOSAR,M5-0-6,Yes,Required,Automated,Implementation,An implicit integral or floating-point conversion shall not reduce the size of the underlying type.,,IntegerConversion,Easy, -AUTOSAR,M5-0-7,Yes,Required,Automated,Implementation,There shall be no explicit floating-integral conversions of a cvalue expression.,,IntegerConversion,Easy, -AUTOSAR,M5-0-8,Yes,Required,Automated,Implementation,An explicit integral or floating-point conversion shall not increase the size of the underlying type of a cvalue expression.,,IntegerConversion,Easy, -AUTOSAR,M5-0-9,Yes,Required,Automated,Implementation,An explicit integral conversion shall not change the signedness of the underlying type of a cvalue expression.,,IntegerConversion,Easy, -AUTOSAR,M5-14-1,Yes,Required,Automated,Implementation,"The right hand operand of a logical &&, || operators shall not contain side effects.",,SideEffects1,Medium, -AUTOSAR,M5-17-1,Yes,Required,Non-Automated,Implementation,The semantic equivalence between a binary operator and its assignment operator form shall be preserved.,,OperatorInvariants,Audit,Produce a list of binary and assigment operator pairs. -AUTOSAR,M5-18-1,Yes,Required,Automated,Implementation,The comma operator shall not be used.,cpp/jsf/av-rule-168,BannedSyntax,Easy, -AUTOSAR,M5-19-1,Yes,Required,Automated,Implementation,Evaluation of constant unsigned integer expressions shall not lead to wrap-around.,,Expressions,Medium, -AUTOSAR,M5-2-10,Yes,Required,Automated,Implementation,The increment (++) and decrement (--) operators shall not be mixed with other operators in an expression.,,OrderOfEvaluation,Easy, -AUTOSAR,M5-2-11,Yes,Required,Automated,Implementation,"The comma operator, && operator and the || operator shall not be overloaded.",,Operators,Easy, -AUTOSAR,M5-2-12,Yes,Required,Automated,Implementation,An identifier with array type passed as a function argument shall not decay to a pointer.,,Pointers,Easy, -AUTOSAR,M5-2-2,Yes,Required,Automated,Implementation,A pointer to a virtual base class shall only be cast to a pointer to a derived class by means of dynamic_cast.,,Pointers,Easy, -AUTOSAR,M5-2-3,Yes,Advisory,Automated,Implementation,Casts from a base class to a derived class should not be performed on polymorphic types.,,Inheritance,Easy, -AUTOSAR,M5-2-6,Yes,Required,Automated,Implementation,"A cast shall not convert a pointer to a function to any other pointer type, including a pointer to function type.",,Pointers,Easy, -AUTOSAR,M5-2-8,Yes,Required,Automated,Implementation,An object with integer type or pointer to void type shall not be converted to an object with pointer type.,,Pointers,Easy, -AUTOSAR,M5-2-9,Yes,Required,Automated,Implementation,A cast shall not convert a pointer type to an integral type.,,Pointers,Easy, -AUTOSAR,M5-3-1,Yes,Required,Automated,Implementation,"Each operand of the ! operator, the logical && or the logical || operators shall have type bool.",,Operators,Easy, -AUTOSAR,M5-3-2,Yes,Required,Automated,Implementation,The unary minus operator shall not be applied to an expression whose underlying type is unsigned.,,Operators,Easy, -AUTOSAR,M5-3-3,Yes,Required,Automated,Implementation,The unary & operator shall not be overloaded.,,Operators,Easy, -AUTOSAR,M5-3-4,Yes,Required,Automated,Implementation,Evaluation of the operand to the sizeof operator shall not contain side effects.,cpp/sizeof-side-effect,SideEffects1,Easy, -AUTOSAR,M5-8-1,Yes,Required,Partially Automated,Implementation,The right hand operand of a shift operator shall lie between zero and one less than the width in bits of the underlying type of the left hand operand.,,Expressions,Medium, -AUTOSAR,M6-2-1,Yes,Required,Automated,Implementation,Assignment operators shall not be used in sub-expressions.,,OrderOfEvaluation,Easy, -AUTOSAR,M6-2-2,Yes,Required,Partially Automated,Implementation,Floating-point expressions shall not be directly or indirectly tested for equality or inequality.,,Expressions,Easy, -AUTOSAR,M6-2-3,Yes,Required,Automated,Implementation,"Before preprocessing, a null statement shall only occur on a line by itself; it may be followed by a comment, provided that the first character following the null statement is a white-space character.",,Comments,Easy, -AUTOSAR,M6-3-1,Yes,Required,Automated,Implementation,"The statement forming the body of a switch, while, do ... while or for statement shall be a compound statement.",,Conditionals,Easy, -AUTOSAR,M6-4-1,Yes,Required,Automated,Implementation,"An if ( condition ) construct shall be followed by a compound statement. The else keyword shall be followed by either a compound statement, or another if statement.",,Conditionals,Easy, -AUTOSAR,M6-4-2,Yes,Required,Automated,Implementation,All if ... else if constructs shall be terminated with an else clause.,,Conditionals,Easy, -AUTOSAR,M6-4-3,Yes,Required,Automated,Implementation,A switch statement shall be a well-formed switch statement.,,Conditionals,Easy, -AUTOSAR,M6-4-4,Yes,Required,Automated,Implementation,A switch-label shall only be used when the most closely-enclosing compound statement is the body of a switch statement.,,Conditionals,Easy, -AUTOSAR,M6-4-5,Yes,Required,Automated,Implementation,An unconditional throw or break statement shall terminate every non-empty switch-clause.,cpp/jsf/av-rule-193,Conditionals,Easy, -AUTOSAR,M6-4-6,Yes,Required,Automated,Implementation,The final clause of a switch statement shall be the default-clause.,,Conditionals,Easy, -AUTOSAR,M6-4-7,Yes,Required,Automated,Implementation,The condition of a switch statement shall not have bool type.,,Conditionals,Easy, -AUTOSAR,M6-5-2,Yes,Required,Automated,Implementation,"If loop-counter is not modified by or ++, then, within condition, the loop-counter shall only be used as an operand to <=, <, > or >=.",,Loops,Easy, -AUTOSAR,M6-5-3,Yes,Required,Automated,Implementation,The loop-counter shall not be modified within condition or statement.,,Loops,Easy, -AUTOSAR,M6-5-4,Yes,Required,Automated,Implementation,"The loop-counter shall be modified by one of: , ++, = n, or + = n; where n remains constant for the duration of the loop.",,Loops,Easy, -AUTOSAR,M6-5-5,Yes,Required,Automated,Implementation,A loop-control-variable other than the loop-counter shall not be modified within condition or expression.,,Loops,Easy, -AUTOSAR,M6-5-6,Yes,Required,Automated,Implementation,A loop-control-variable other than the loop-counter which is modified in statement shall have type bool.,,Loops,Easy, -AUTOSAR,M6-6-1,Yes,Required,Automated,Implementation,"Any label referenced by a goto statement shall be declared in the same block, or in a block enclosing the goto statement.",,Conditionals,Easy, -AUTOSAR,M6-6-2,Yes,Required,Automated,Implementation,The goto statement shall jump to a label declared later in the same function body.,,Conditionals,Easy, -AUTOSAR,M6-6-3,Yes,Required,Automated,Implementation,The continue statement shall only be used within a well-formed for loop.,,Conditionals,Easy, -AUTOSAR,M7-1-2,Yes,Required,Automated,Implementation,A pointer or reference parameter in a function shall be declared as pointer to const or reference to const if the corresponding object is not modified.,,Const,Hard, -AUTOSAR,M7-3-1,Yes,Required,Automated,Implementation,"The global namespace shall only contain main, namespace declarations and extern ""C"" declarations.",,Scope,Easy, -AUTOSAR,M7-3-2,Yes,Required,Automated,Implementation,The identifier main shall not be used for a function other than the global function main.,,Naming,Easy, -AUTOSAR,M7-3-3,Yes,Required,Automated,Implementation,There shall be no unnamed namespaces in header files.,,Naming,Easy, -AUTOSAR,M7-3-4,Yes,Required,Automated,Implementation,Using-directives shall not be used.,,BannedSyntax,Easy, -AUTOSAR,M7-3-6,Yes,Required,Automated,Implementation,Using-directives and using-declarations (excluding class scope or function scope using-declarations) shall not be used in header files.,,BannedSyntax,Easy, -AUTOSAR,M7-4-1,Yes,Required,Non-Automated,Implementation,All usage of assembler shall be documented.,,BannedLibraries,Audit,List all the places where assembler is used. -AUTOSAR,M7-4-2,Yes,Required,Automated,Implementation,Assembler instructions shall only be introduced using the asm declaration.,A7-4-1,Functions,Easy, -AUTOSAR,M7-4-3,Yes,Required,Automated,Implementation,Assembly language shall be encapsulated and isolated.,,Functions,Easy, -AUTOSAR,M7-5-1,Yes,Required,Non-Automated,Implementation,"A function shall not return a reference or a pointer to an automatic variable (including parameters), defined within the function.",,Functions,Medium,Similar to M7-5-2. -AUTOSAR,M7-5-2,Yes,Required,Non-Automated,Implementation,The address of an object with automatic storage shall not be assigned to another object that may persist after the first object has ceased to exist.,EXP54-CPP,Freed,Hard,Identify address of expressions for automatic storage objects which flow (via data flow) to some expression which escapes. -AUTOSAR,M8-0-1,Yes,Required,Automated,Implementation,An init-declarator-list or a member-declarator-list shall consist of a single init-declarator or member-declarator respectively.,,Initialization,Easy, -AUTOSAR,M8-3-1,Yes,Required,Automated,Implementation,"Parameters in an overriding virtual function shall either use the same default arguments as the function they override, or else shall not specify any default arguments.",,VirtualFunctions,Easy, -AUTOSAR,M8-4-2,Yes,Required,Automated,Implementation,The identifiers used for the parameters in a re-declaration of a function shall be identical to those in the declaration.,M3-9-1,Naming,Easy, -AUTOSAR,M8-4-4,Yes,Required,Automated,Implementation,A function identifier shall either be used to call the function or it shall be preceded by &.,,Functions,Easy, -AUTOSAR,M8-5-2,Yes,Required,Automated,Implementation,Braces shall be used to indicate and match the structure in the non-zero initialization of arrays and structures.,,Initialization,Easy, -AUTOSAR,M9-3-1,Yes,Required,Automated,Implementation,Const member functions shall not return non-const pointers or references to class-data.,,Const,Easy, -AUTOSAR,M9-3-3,Yes,Required,Automated,Implementation,"If a member function can be made static then it shall be made static, otherwise if it can be made const then it shall be made const.",,Const,Easy, -AUTOSAR,M9-6-1,No,Required,Non-Automated,Implementation,"When the absolute positioning of bits representing a bit-field is required, then the behavior and packing of bit-fields shall be documented.",,,,Documentation not covered by queries -AUTOSAR,M9-6-4,Yes,Required,Automated,Implementation,Named bit-fields with signed integer type shall have a length of more than one bit.,,Representation,Easy, -CERT-C++,CON50-CPP,Yes,Rule,,,Do not destroy a mutex while it is locked,,Concurrency,Hard, -CERT-C++,CON51-CPP,Yes,Rule,,,Ensure actively held locks are released on exceptional conditions,,Concurrency,Easy, -CERT-C++,CON52-CPP,Yes,Rule,,,Prevent data races when accessing bit-fields from multiple threads,,Concurrency,Medium, -CERT-C++,CON53-CPP,Yes,Rule,,,Avoid deadlock by locking in a predefined order,,Concurrency,Very Hard, -CERT-C++,CON54-CPP,Yes,Rule,,,Wrap functions that can spuriously wake up in a loop,,Concurrency,Medium, -CERT-C++,CON55-CPP,Yes,Rule,,,Preserve thread safety and liveness when using condition variables,,Concurrency,Hard, -CERT-C++,CON56-CPP,Yes,Rule,,,Do not speculatively lock a non-recursive mutex that is already owned by the calling thread,cpp/twice-locked???,Concurrency,Hard, -CERT-C++,CTR50-CPP,Yes,Rule,,,Guarantee that container indices and iterators are within the valid range,,OutOfBounds,Very Hard, -CERT-C++,CTR51-CPP,Yes,Rule,,,"Use valid references, pointers, and iterators to reference elements of a container",,Iterators,Hard, -CERT-C++,CTR52-CPP,Yes,Rule,,,Guarantee that library functions do not overflow,,OutOfBounds,Very Hard, -CERT-C++,CTR53-CPP,Yes,Rule,,,Use valid iterator ranges,,Iterators,Hard, -CERT-C++,CTR54-CPP,Yes,Rule,,,Do not subtract iterators that do not refer to the same container,,Iterators,Hard, -CERT-C++,CTR55-CPP,Yes,Rule,,,Do not use an additive operator on an iterator if the result would overflow,,Iterators,Hard, -CERT-C++,CTR56-CPP,Yes,Rule,,,Do not use pointer arithmetic on polymorphic objects,,Pointers,Easy, -CERT-C++,CTR57-CPP,Yes,Rule,,,Provide a valid ordering predicate,,Invariants,Medium, -CERT-C++,CTR58-CPP,Yes,Rule,,,Predicate function objects should not be mutable,,SideEffects2,Medium, -CERT-C++,DCL50-CPP,Yes,Rule,,,Do not define a C-style variadic function,,BannedSyntax,Easy, -CERT-C++,DCL51-CPP,Yes,Rule,,,Do not declare or define a reserved identifier,,Naming,Medium, -CERT-C++,DCL52-CPP,No,Rule,,,Never qualify a reference type with const or volatile,,,,"This is compiler checked - clang reports an error. The extractor accepts it, but doesn't include the cv information." -CERT-C++,DCL53-CPP,Yes,Rule,,,Do not write syntactically ambiguous declarations,,Scope,Medium, -CERT-C++,DCL54-CPP,Yes,Rule,,,Overload allocation and deallocation functions as a pair in the same scope,,Scope,Easy, -CERT-C++,DCL55-CPP,Yes,Rule,,,Avoid information leakage when passing a class object across a trust boundary,,Uninitialized,Very Hard, -CERT-C++,DCL56-CPP,Yes,Rule,,,Avoid cycles during initialization of static objects,,Initialization,Easy, -CERT-C++,DCL57-CPP,Yes,Rule,,,Do not let exceptions escape from destructors or deallocation functions,A15-5-1,Exceptions2,Easy, -CERT-C++,DCL58-CPP,Yes,Rule,,,Do not modify the standard namespaces,,Scope,Easy, -CERT-C++,DCL59-CPP,Yes,Rule,,,Do not define an unnamed namespace in a header file,,Scope,Easy, -CERT-C++,DCL60-CPP,Yes,Rule,,,Obey the one-definition rule,M3-2-2,Scope,Easy, -CERT-C++,ERR50-CPP,Yes,Rule,,,Do not abruptly terminate the program,,Exceptions1,Medium, -CERT-C++,ERR51-CPP,Yes,Rule,,,Handle all exceptions,,Exceptions1,Easy, -CERT-C++,ERR52-CPP,Yes,Rule,,,Do not use setjmp() or longjmp(),cpp/jsf/av-rule-20,BannedFunctions,Easy, -CERT-C++,ERR53-CPP,Yes,Rule,,,Do not reference base classes or class data members in a constructor or destructor function-try-block handler,,Exceptions1,Easy, -CERT-C++,ERR54-CPP,Yes,Rule,,,Catch handlers should order their parameter types from most derived to least derived,,Exceptions2,Easy, -CERT-C++,ERR55-CPP,Yes,Rule,,,Honor exception specifications,A15-4-2,Exceptions1,Medium, -CERT-C++,ERR56-CPP,Yes,Rule,,,Guarantee exception safety,,ExceptionSafety,Hard, -CERT-C++,ERR57-CPP,Yes,Rule,,,Do not leak resources when handling exceptions,,ExceptionSafety,Hard, -CERT-C++,ERR58-CPP,Yes,Rule,,,Handle all exceptions thrown before main() begins executing,,Exceptions1,Easy, -CERT-C++,ERR59-CPP,Yes,Rule,,,Do not throw an exception across execution boundaries,,TrustBoundaries,Hard, -CERT-C++,ERR60-CPP,Yes,Rule,,,Exception objects must be nothrow copy constructible,,Exceptions1,Medium, -CERT-C++,ERR61-CPP,Yes,Rule,,,Catch exceptions by lvalue reference,,Exceptions1,Easy, -CERT-C++,ERR62-CPP,Yes,Rule,,,Detect errors when converting a string to a number,A18-0-2,TypeRanges,Medium, -CERT-C++,EXP50-CPP,Yes,Rule,,,Do not depend on the order of evaluation for side effects,,SideEffects1,Hard, -CERT-C++,EXP51-CPP,Yes,Rule,,,Do not delete an array through a pointer of the incorrect type,,Freed,Hard, -CERT-C++,EXP52-CPP,Yes,Rule,,,Do not rely on side effects in unevaluated operands,,SideEffects1,Medium, -CERT-C++,EXP53-CPP,Yes,Rule,,,Do not read uninitialized memory,cpp/not-initialised???,Uninitialized,Very Hard, -CERT-C++,EXP54-CPP,Yes,Rule,,,Do not access an object outside of its lifetime,,Freed,Very Hard, -CERT-C++,EXP55-CPP,Yes,Rule,,,Do not access a cv-qualified object through a cv-unqualified type,,Const,Easy, -CERT-C++,EXP56-CPP,Yes,Rule,,,Do not call a function with a mismatched language linkage,,Functions,Easy, -CERT-C++,EXP57-CPP,Yes,Rule,,,Do not cast or delete pointers to incomplete classes,,Pointers,Medium, -CERT-C++,EXP58-CPP,Yes,Rule,,,Pass an object of the correct type to va_start,,Expressions,Medium, -CERT-C++,EXP59-CPP,Yes,Rule,,,Use offsetof() on valid types and members,,Classes,Medium, -CERT-C++,EXP60-CPP,Yes,Rule,,,Do not pass a nonstandard-layout type object across execution boundaries,,TrustBoundaries,Hard, -CERT-C++,EXP61-CPP,Yes,Rule,,,A lambda object must not outlive any of its reference captured objects,EXP54-CPP,Lambdas,Medium, -CERT-C++,EXP62-CPP,Yes,Rule,,,Do not access the bits of an object representation that are not part of the object's value representation,,Representation,Easy, -CERT-C++,EXP63-CPP,Yes,Rule,,,Do not rely on the value of a moved-from object,,MoveForward,Hard, -CERT-C++,FIO50-CPP,Yes,Rule,,,Do not alternately input and output from a file stream without an intervening positioning call,,IO,Medium, -CERT-C++,FIO51-CPP,Yes,Rule,,,Close files when they are no longer needed,,IO,Medium, -CERT-C++,INT50-CPP,Yes,Rule,,,Do not cast to an out-of-range enumeration value,A7-2-1,TypeRanges,Hard, -CERT-C++,MEM50-CPP,Yes,Rule,,,Do not access freed memory,cpp/use-after-free,Freed,Very Hard, -CERT-C++,MEM51-CPP,Yes,Rule,,,Properly deallocate dynamically allocated resources,cpp/memory-never-freed???,Allocations,Very Hard, -CERT-C++,MEM52-CPP,Yes,Rule,,,Detect and handle memory allocation errors,,Allocations,Medium, -CERT-C++,MEM53-CPP,Yes,Rule,,,Explicitly construct and destruct objects when manually managing object lifetime,,Allocations,Medium, -CERT-C++,MEM54-CPP,Yes,Rule,,,Provide placement new with properly aligned pointers to sufficient storage capacity,,Allocations,Hard, -CERT-C++,MEM55-CPP,Yes,Rule,,,Honor replacement dynamic storage management requirements,,Allocations,Hard, -CERT-C++,MEM56-CPP,Yes,Rule,,,Do not store an already-owned pointer value in an unrelated smart pointer,,SmartPointers2,Very Hard, -CERT-C++,MEM57-CPP,Yes,Rule,,,Avoid using default operator new for over-aligned types,,Allocations,Easy, -CERT-C++,MSC50-CPP,Yes,Rule,,,Do not use std::rand() for generating pseudorandom numbers,,BannedFunctions,Easy, -CERT-C++,MSC51-CPP,Yes,Rule,,,Ensure your random number generator is properly seeded,,Initialization,Medium, -CERT-C++,MSC52-CPP,Yes,Rule,,,Value-returning functions must return a value from all exit paths,cpp/missing-return,Functions,Easy, -CERT-C++,MSC53-CPP,Yes,Rule,,,Do not return from a function declared [[noreturn]],,Functions,Easy, -CERT-C++,MSC54-CPP,Yes,Rule,,,A signal handler must be a plain old function,,Invariants,Medium, -CERT-C++,OOP50-CPP,Yes,Rule,,,Do not invoke virtual functions from constructors or destructors,,Inheritance,Easy, -CERT-C++,OOP51-CPP,Yes,Rule,,,Do not slice derived objects,,Inheritance,Medium, -CERT-C++,OOP52-CPP,Yes,Rule,,,Do not delete a polymorphic object without a virtual destructor,A12-4-1,Inheritance,Easy, -CERT-C++,OOP53-CPP,Yes,Rule,,,Write constructor member initializers in the canonical order,,Initialization,Easy, -CERT-C++,OOP54-CPP,Yes,Rule,,,Gracefully handle self-copy assignment,"cpp/jsf/av-rule-81?, cpp/self-assignment-check?",OperatorInvariants,Hard, -CERT-C++,OOP55-CPP,Yes,Rule,,,Do not use pointer-to-member operators to access nonexistent members,,Pointers,Medium, -CERT-C++,OOP56-CPP,Yes,Rule,,,Honor replacement handler requirements,,Invariants,Easy, -CERT-C++,OOP57-CPP,Yes,Rule,,,Prefer special member functions and overloaded operators to C Standard Library functions,EXP62-CPP,BannedFunctions,Easy, -CERT-C++,OOP58-CPP,Yes,Rule,,,Copy operations must not mutate the source object,,OperatorInvariants,Medium, -CERT-C++,STR50-CPP,Yes,Rule,,,Guarantee that storage for strings has sufficient space for character data and the null terminator,,Strings,Very Hard, -CERT-C++,STR51-CPP,Yes,Rule,,,Do not attempt to create a std::string from a null pointer,,Null,Hard, -CERT-C++,STR52-CPP,Yes,Rule,,,"Use valid references, pointers, and iterators to reference elements of a basic_string",,Iterators,Hard, -CERT-C++,STR53-CPP,Yes,Rule,,,Range check element access,,OutOfBounds,Hard, \ No newline at end of file +Language,Standard,ID,Queryable?,Obligation level,Enforcement level,Allocated target,Description,Similar,Package,Difficulty,Justification for querability level +cpp,AUTOSAR,A0-1-1,Yes,Required,Automated,Implementation,A project shall not contain instances of non-volatile variables being given values that are not subsequently used.,M0-1-6,DeadCode,Medium, +cpp,AUTOSAR,A0-1-2,Yes,Required,Automated,Implementation,The value returned by a function having a non-void return type that is not an overloaded operator shall be used.,M0-1-7,DeadCode,Easy, +cpp,AUTOSAR,A0-1-3,Yes,Required,Automated,Implementation,"Every function defined in an anonymous namespace, or static function with internal linkage, or private member function shall be used.",M0-1-10,DeadCode,Easy, +cpp,AUTOSAR,A0-1-4,Yes,Required,Automated,Implementation,There shall be no unused named parameters in non-virtual functions.,,DeadCode,Easy, +cpp,AUTOSAR,A0-1-5,Yes,Required,Automated,Implementation,There shall be no unused named parameters in the set of parameters for a virtual function and all the functions that override it.,,DeadCode,Easy, +cpp,AUTOSAR,A0-1-6,Yes,Advisory,Automated,Implementation,There should be no unused type declarations.,M0-1-5,DeadCode,Easy, +cpp,AUTOSAR,A0-4-1,Yes,Required,Non-Automated,Infrastructure / Toolchain,Floating-point implementation shall comply with IEEE 754 standard.,,Toolchain,Easy,Find certain pairs of types and platforms which are not IEEE 754 compatible. +cpp,AUTOSAR,A0-4-2,Yes,Required,Automated,Implementation,Type long double shall not be used.,,BannedTypes,Easy, +cpp,AUTOSAR,A0-4-3,Yes,Required,Automated,Toolchain,The implementations in the chosen compiler shall strictly comply with the C++14 Language Standard.,,Toolchain,Easy,Find cases where -std=gnu++14 is used instead of -std=c++14. Note: this is currently only possible for compilations that do not use response files. +cpp,AUTOSAR,A0-4-4,Yes,Required,Partially Automated,Implementation,"Range, domain and pole errors shall be checked when using math functions.",,TypeRanges,Hard, +cpp,AUTOSAR,A1-1-1,Yes,Required,Automated,Implementation,All code shall conform to ISO/IEC 14882:2014 - Programming Language C++ and shall not use deprecated features.,,Toolchain,Hard,"Appendix D of the Standard lists depreceated features. List is lengthy, but otherwise easy to write. This can also be compiler checked, so we should confirm that we also want this as a CodeQL check." +cpp,AUTOSAR,A1-1-2,Yes,Required,Non-Automated,Implementation / Toolchain,A warning level of the compilation process shall be set in compliance with project policies.,,Toolchain,Easy,Note: this is currently only possible for compilations that do not use response files. +cpp,AUTOSAR,A1-1-3,Yes,Required,Non-Automated,Toolchain,An optimization option that disregards strict standard compliance shall not be turned on in the chosen compiler.,,Toolchain,Easy,Note: this is currently only possible for compilations that do not use response files. +cpp,AUTOSAR,A1-2-1,No,Required,Non-Automated,Toolchain,"When using a compiler toolchain (including preprocessor, compiler itself, linker, C++ standard libraries) in safety-related software, the tool confidence level (TCL) shall be determined. In case of TCL2 or TCL3, the compiler shall undergo a 'Qualification of a software tool', as per ISO 26262-8.11.4.6 [6].",,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,A1-4-1,No,Required,Non-Automated,Implementation / Verification,Code metrics and their valid boundaries shall be defined and code shall comply with defined boundaries of code metrics.,,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,A1-4-3,No,Advisory,Automated,Implementation,All code should compile free of compiler warnings.,,,,"This should be checked via the compiler output, rather than CodeQL, which adds unecessary steps." +cpp,AUTOSAR,A10-0-1,Yes,Required,Non-Automated,Design,Public inheritance shall be used to implement 'is-a' relationship.,,Inheritance,Audit,Report a list of Inheritance relationships. +cpp,AUTOSAR,A10-0-2,Yes,Required,Non-Automated,Design,Membership or non-public inheritance shall be used to implement 'has-a' relationship.,,Inheritance,Audit,Report a list of membership relationships. +cpp,AUTOSAR,A10-1-1,Yes,Required,Automated,Implementation,Class shall not be derived from more than one base class which is not an interface class.,,Inheritance,Easy, +cpp,AUTOSAR,A10-2-1,Yes,Required,Automated,Implementation,Non-virtual public or protected member functions shall not be redefined in derived classes.,,VirtualFunctions,Easy, +cpp,AUTOSAR,A10-3-1,Yes,Required,Automated,Implementation,"Virtual function declaration shall contain exactly one of the three specifiers: (1) virtual, (2) override, (3) final.",,VirtualFunctions,Easy, +cpp,AUTOSAR,A10-3-2,Yes,Required,Automated,Implementation,Each overriding virtual function shall be declared with the override or final specifier.,,VirtualFunctions,Easy, +cpp,AUTOSAR,A10-3-3,Yes,Required,Automated,Implementation,Virtual functions shall not be introduced in a final class.,,VirtualFunctions,Easy, +cpp,AUTOSAR,A10-3-5,Yes,Required,Automated,Implementation,A user-defined assignment operator shall not be virtual.,,Operators,Easy, +cpp,AUTOSAR,A10-4-1,Yes,Advisory,Non-Automated,Design,Hierarchies should be based on interface classes.,,Inheritance,Audit,Report a list of hierarchies which don't use interfaces. +cpp,AUTOSAR,A11-0-1,Yes,Advisory,Automated,Implementation,A non-POD type should be defined as class.,,Classes,Easy, +cpp,AUTOSAR,A11-0-2,Yes,Required,Automated,Implementation,"A type defined as struct shall: (1) provide only public data members, (2) not provide any special member functions or methods, (3) not be a base of another struct or class, (4) not inherit from another struct or class.",,Classes,Easy, +cpp,AUTOSAR,A11-3-1,Yes,Required,Automated,Implementation,Friend declarations shall not be used.,cpp/jsf/av-rule-70,BannedSyntax,Easy, +cpp,AUTOSAR,A12-0-1,Yes,Required,Automated,Implementation,"If a class declares a copy or move operation, or a destructor, either via '=default', '=delete', or via a user-provided declaration, then all others of these five special member functions shall be declared as well.",cpp/rule-of-three,Classes,Easy, +cpp,AUTOSAR,A12-0-2,Yes,Required,Partially Automated,Implementation,Bitwise operations and operations that assume data representation in memory shall not be performed on objects.,M5-0-21,Expressions,Medium, +cpp,AUTOSAR,A12-1-1,Yes,Required,Automated,Implementation,"Constructors shall explicitly initialize all virtual base classes, all direct non-virtual base classes and all non-static data members.",M12-1-2,Initialization,Medium, +cpp,AUTOSAR,A12-1-2,Yes,Required,Automated,Implementation,Both NSDMI and a non-static member initializer in a constructor shall not be used in the same type.,,Initialization,Medium, +cpp,AUTOSAR,A12-1-3,Yes,Required,Automated,Implementation,"If all user-defined constructors of a class initialize data members with constant values that are the same across all constructors, then data members shall be initialized using NSDMI instead.",,Initialization,Medium, +cpp,AUTOSAR,A12-1-4,Yes,Required,Automated,Implementation,All constructors that are callable with a single argument of fundamental type shall be declared explicit.,,Initialization,Easy, +cpp,AUTOSAR,A12-1-5,Yes,Required,Partially Automated,Implementation,Common class initialization for non-constant members shall be done by a delegating constructor.,,Initialization,Medium, +cpp,AUTOSAR,A12-1-6,Yes,Required,Automated,Implementation,Derived classes that do not need further explicit initialization and require all the constructors from the base class shall use inheriting constructors.,,Initialization,Easy, +cpp,AUTOSAR,A12-4-1,Yes,Required,Automated,Implementation,"Destructor of a base class shall be public virtual, public override or protected non-virtual.",OOP52-CPP,VirtualFunctions,Easy, +cpp,AUTOSAR,A12-4-2,Yes,Advisory,Automated,Implementation,"If a public destructor of a class is non-virtual, then the class should be declared final.",,VirtualFunctions,Easy, +cpp,AUTOSAR,A12-6-1,Yes,Required,Automated,Implementation,All class data members that are initialized by the constructor shall be initialized using member initializers.,,Classes,Easy, +cpp,AUTOSAR,A12-7-1,Yes,Required,Automated,Implementation,"If the behavior of a user-defined special member function is identical to implicitly defined special member function, then it shall be defined '=default' or be left undefined.",,Classes,Easy, +cpp,AUTOSAR,A12-8-1,Yes,Required,Automated,Implementation,"Move and copy constructors shall move and respectively copy base classes and data members of a class, without any side effects.",M12-8-1,SideEffects2,Hard, +cpp,AUTOSAR,A12-8-2,Yes,Advisory,Automated,Implementation,User-defined copy and move assignment operators should use user-defined no-throw swap function.,,OperatorInvariants,Easy, +cpp,AUTOSAR,A12-8-3,Yes,Required,Partially Automated,Implementation,Moved-from object shall not be read-accessed.,EXP63-CPP,MoveForward,Import, +cpp,AUTOSAR,A12-8-4,Yes,Required,Automated,Implementation,Move constructor shall not initialize its class members and base classes using copy semantics.,,Initialization,Easy, +cpp,AUTOSAR,A12-8-5,Yes,Required,Automated,Implementation,A copy assignment and a move assignment operators shall handle self-assignment.,OOP54-CPP,OperatorInvariants,Import, +cpp,AUTOSAR,A12-8-6,Yes,Required,Automated,Implementation,Copy and move constructors and copy assignment and move assignment operators shall be declared protected or defined '=delete' in base class.,M12-8-2,Operators,Easy, +cpp,AUTOSAR,A12-8-7,Yes,Advisory,Automated,Implementation,Assignment operators should be declared with the ref-qualifier &.,,Operators,Easy, +cpp,AUTOSAR,A13-1-2,Yes,Required,Automated,Implementation,User defined suffixes of the user defined literal operators shall start with underscore followed by one or more letters.,,Naming,Easy, +cpp,AUTOSAR,A13-1-3,Yes,Required,Automated,Implementation,User defined literals operators shall only perform conversion of passed parameters.,,SideEffects2,Easy, +cpp,AUTOSAR,A13-2-1,Yes,Required,Automated,Implementation,An assignment operator shall return a reference to 'this'.,cpp/assignment-does-not-return-this,OperatorInvariants,Easy, +cpp,AUTOSAR,A13-2-2,Yes,Required,Automated,Implementation,A binary arithmetic operator and a bitwise operator shall return a 'prvalue'.,,OperatorInvariants,Easy, +cpp,AUTOSAR,A13-2-3,Yes,Required,Automated,Implementation,A relational operator shall return a boolean value.,,Operators,Easy, +cpp,AUTOSAR,A13-3-1,Yes,Required,Automated,Implementation,A function that contains 'forwarding reference' as its argument shall not be overloaded.,,Operators,Easy, +cpp,AUTOSAR,A13-5-1,Yes,Required,Automated,Implementation,"If 'operator[]' is to be overloaded with a non-const version, const version shall also be implemented.",,Operators,Easy, +cpp,AUTOSAR,A13-5-2,Yes,Required,Automated,Implementation,All user-defined conversion operators shall be defined explicit.,,Operators,Easy, +cpp,AUTOSAR,A13-5-3,Yes,Advisory,Automated,Implementation,User-defined conversion operators should not be used.,,Operators,Easy, +cpp,AUTOSAR,A13-5-4,Yes,Required,Automated,Implementation,"If two opposite operators are defined, one shall be defined in terms of the other.",,OperatorInvariants,Easy, +cpp,AUTOSAR,A13-5-5,Yes,Required,Automated,Implementation,Comparison operators shall be non-member functions with identical parameter types and noexcept.,,Operators,Easy, +cpp,AUTOSAR,A13-6-1,Yes,Required,Automated,Implementation,"Digit sequences separators ' shall only be used as follows: (1) for decimal, every 3 digits, (2) for hexadecimal, every 2 digits, (3) for binary, every 4 digits.",,Literals,Easy, +cpp,AUTOSAR,A14-1-1,Yes,Advisory,Non-Automated,Implementation,A template should check if a specific template argument is suitable for this template.,,Templates,Medium,"Look for classes with default constructors or assignment operators, with a template field which is not copyable/moveable" +cpp,AUTOSAR,A14-5-1,Yes,Required,Automated,Implementation,A template constructor shall not participate in overload resolution for a single argument of the enclosing class type.,M14-5-2,Templates,Easy, +cpp,AUTOSAR,A14-5-2,Yes,Advisory,Partially-Automated,Design,Class members that are not dependent on template class parameters should be defined in a separate base class.,,Classes,Easy, +cpp,AUTOSAR,A14-5-3,Yes,Advisory,Automated,Design,"A non-member generic operator shall only be declared in a namespace that does not contain class (struct) type, enum type or union type declarations.",,Operators,Easy, +cpp,AUTOSAR,A14-7-1,Yes,Required,Automated,Implementation,A type used as a template argument shall provide all members that are used by the template.,M14-7-2,Templates,Easy, +cpp,AUTOSAR,A14-7-2,Yes,Required,Automated,Implementation,"Template specialization shall be declared in the same file (1) as the primary template (2) as a user-defined type, for which the specialization is declared.",,Templates,Easy, +cpp,AUTOSAR,A14-8-2,Yes,Required,Automated,Implementation,Explicit specializations of function templates shall not be used.,M14-8-1,Templates,Easy, +cpp,AUTOSAR,A15-0-1,Yes,Required,Non-Automated,Architecture / Design / Implementation,A function shall not exit with an exception if it is able to complete its task.,,Exceptions1,Audit,Report a list of functions which throw exceptions. +cpp,AUTOSAR,A15-0-2,Yes,Required,Partially Automated,Architecture / Design / Implementation,"At least the basic guarantee for exception safety shall be provided for all operations. In addition, each function may offer either the strong guarantee or the nothrow guarantee",ERR56-CPP,ExceptionSafety,Import, +cpp,AUTOSAR,A15-0-3,Yes,Required,Non-Automated,Implementation,Exception safety guarantee of a called function shall be considered.,,ExceptionSafety,Hard,"There are certain exception safety guarantees we can check, such as exceptions in constructor calls used in emplace (the example from the rule text)." +cpp,AUTOSAR,A15-0-4,Yes,Required,Non-Automated,Architecture / Design / Implementation,Unchecked exceptions shall be used to represent errors from which the caller cannot reasonably be expected to recover.,,Exceptions1,Audit,Report a list of unchecked exceptions. +cpp,AUTOSAR,A15-0-5,Yes,Required,Non-Automated,Architecture / Design / Implementation,Checked exceptions shall be used to represent errors from which the caller can reasonably be expected to recover.,,Exceptions1,Audit,Report a list of checked exceptions. +cpp,AUTOSAR,A15-0-6,No,Required,Non-Automated,Verification / Toolchain,An analysis shall be performed to analyze the failure modes of exception,,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,A15-0-7,No,Required,Partially Automated,Verification / Toolchain,Exception handling mechanism shall guarantee a deterministic worst-case time execution time.,,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,A15-0-8,No,Required,Non-Automated,Verification / Toolchain,"A worst-case execution time (WCET) analysis shall be performed to determine maximum execution time constraints of the software, covering in particular the exceptions processing.",,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,A15-1-1,Yes,Advisory,Automated,Implementation,Only instances of types derived from std::exception should be thrown.,,Exceptions2,Easy, +cpp,AUTOSAR,A15-1-2,Yes,Required,Automated,Implementation,An exception object shall not be a pointer.,,Exceptions1,Easy, +cpp,AUTOSAR,A15-1-3,Yes,Advisory,Automated,Implementation,All thrown exceptions should be unique.,,Exceptions1,Easy, +cpp,AUTOSAR,A15-1-4,Yes,Required,Partially Automated,Implementation,"If a function exits with an exception, then before a throw, the function shall place all objects/resources that the function constructed in valid states or it shall delete them.",ERR57-CPP,ExceptionSafety,Easy, +cpp,AUTOSAR,A15-1-5,Yes,Required,Non-Automated,Implementation,Exceptions shall not be thrown across execution boundaries.,ERR59-CPP,TrustBoundaries,Import,The database holds information about which compiler binary was used for each compilation. This can be used to identify execution boundaries between compilation units. +cpp,AUTOSAR,A15-2-1,Yes,Required,Automated,Implementation,Constructors that are not noexcept shall not be invoked before program startup.,ERR51-CPP,Exceptions1,Medium, +cpp,AUTOSAR,A15-2-2,Yes,Required,Partially Automated,Implementation,"If a constructor is not noexcept and the constructor cannot finish object initialization, then it shall deallocate the object's resources and it shall throw an exception.",ERR57-CPP,Exceptions2,Easy, +cpp,AUTOSAR,A15-3-2,No,Required,Non-Automated,Implementation,"If a function throws an exception, it shall be handled when meaningful actions can be taken, otherwise it shall be propagated.",,,,Difficult to identify when meaningful action could be taken. +cpp,AUTOSAR,A15-3-3,Yes,Required,Partially-Automated,Implementation,"Main function and a task main function shall catch at least: base class exceptions from all third-party libraries used, std::exception and all otherwise unhandled exceptions.",M15-3-2,Exceptions1,Easy, +cpp,AUTOSAR,A15-3-4,Yes,Required,Non-Automated,Implementation,"Catch-all (ellipsis and std::exception) handlers shall be used only in (a) main, (b) task main functions, (c) in functions that are supposed to isolate independent components and (d) when calling third-party code that uses exceptions not according to AUTOSAR C++14 guidelines.",,Exceptions1,Medium,"Identify catch-all handlers which aren't in main, aren't in functions called by std::thread or similar, and aren't wrapping external function calls. We may require some heuristics to exclude other ""isolation"" cases." +cpp,AUTOSAR,A15-3-5,Yes,Required,Automated,Implementation,A class type exception shall be caught by reference or const reference.,M15-3-5,Exceptions2,Easy, +cpp,AUTOSAR,A15-4-1,Yes,Required,Automated,Implementation,Dynamic exception-specification shall not be used.,,Exceptions1,Easy, +cpp,AUTOSAR,A15-4-2,Yes,Required,Automated,Implementation,"If a function is declared to be noexcept, noexcept(true) or noexcept(), then it shall not exit with an exception.",M15-5-2,Exceptions1,Medium, +cpp,AUTOSAR,A15-4-3,Yes,Required,Automated,Implementation,"The noexcept specification of a function shall either be identical across all translation units, or identical or more restrictive between a virtual member function and an overrider.",,Exceptions2,Easy, +cpp,AUTOSAR,A15-4-4,Yes,Required,Automated,Implementation,A declaration of non-throwing function shall contain noexcept specification.,,Exceptions1,Easy, +cpp,AUTOSAR,A15-4-5,Yes,Required,Automated,Implementation,Checked exceptions that could be thrown from a function shall be specified together with the function declaration and they shall be identical in all function declarations and for all its overriders.,,Exceptions2,Easy, +cpp,AUTOSAR,A15-5-1,Yes,Required,Automated,Implementation,"All user-provided class destructors, deallocation functions, move constructors, move assignment operators and swap functions shall not exit with an exception. A noexcept exception specification shall be added to these functions as appropriate.",M15-5-1,Exceptions2,Easy, +cpp,AUTOSAR,A15-5-2,Yes,Required,Partially Automated,Implementation,"Program shall not be abruptly terminated. In particular, an implicit or explicit invocation of std::abort(), std::quick_exit(), std::_Exit(), std::terminate() shall not be done.",ERR50-CPP,Exceptions1,Easy, +cpp,AUTOSAR,A15-5-3,Yes,Required,Automated,Implementation,The std::terminate() function shall not be called implicitly.,A15-5-2,Exceptions1,Medium, +cpp,AUTOSAR,A16-0-1,Yes,Required,Automated,Implementation,"The pre-processor shall only be used for unconditional and conditional file inclusion and include guards, and using the following directives: (1) #ifndef, #ifdef, (3) #if, (4) #if defined, (5) #elif, (6) #else, (7) #define, (8) #endif, (9) #include.",M16-2-1,Macros,Easy, +cpp,AUTOSAR,A16-2-1,Yes,Required,Automated,Implementation,"The ', "", /*, //, \ characters shall not occur in a header file name or in #include directive.",M16-2-4,Macros,Easy, +cpp,AUTOSAR,A16-2-2,Yes,Required,Automated,Implementation,There shall be no unused include directives.,cpp/dependency/useless-include,Includes,Hard,https://github.com/github/semmle-code/tree/main/packs/dependency/queries/semmlecode-cpp-queries/Dependency +cpp,AUTOSAR,A16-2-3,No,Required,Non-Automated,Implementation,An include directive shall be added explicitly for every symbol used in a file.,,,,There is no automated way to identify which headers are intended to be imported for each symbol. For the standard library we could scrape the documentation to determine which symbol is supposed to come from which header but the expected value is low. +cpp,AUTOSAR,A16-6-1,Yes,Required,Automated,Implementation,#error directive shall not be used.,,Macros,Easy, +cpp,AUTOSAR,A16-7-1,Yes,Required,Automated,Implementation,The #pragma directive shall not be used.,,Macros,Easy, +cpp,AUTOSAR,A17-0-1,Yes,Required,Automated,Implementation,"Reserved identifiers, macros and functions in the C++ standard library shall not be defined, redefined or undefined.",M17-0-1,BannedLibraries,Medium, +cpp,AUTOSAR,A17-0-2,No,Required,Non-Automated,Implementation,All project's code including used libraries (including standard and user-defined libraries) and any third-party user code shall conform to the AUTOSAR C++14 Coding Guidelines.,,,,"Self-referential. This is, in practice, covered by the rest of the queries, so I don't think we would have a specific query for this." +cpp,AUTOSAR,A17-1-1,Yes,Required,Non-Automated,Implementation,Use of the C Standard Library shall be encapsulated and isolated.,,Functions,Medium,Enforce that functions which call cstd functions are only calling cstd functions. +cpp,AUTOSAR,A17-6-1,Yes,Required,Automated,Implementation,Non-standard entities shall not be added to standard namespaces.,DCL58-CPP,Scope,Import, +cpp,AUTOSAR,A18-0-1,Yes,Required,Automated,Implementation,The C library facilities shall only be accessed through C++ library headers.,M18-0-1,BannedLibraries,Easy, +cpp,AUTOSAR,A18-0-2,Yes,Required,Automated,Implementation,The error state of a conversion from string to a numeric value shall be checked.,M18-0-2,TypeRanges,Medium, +cpp,AUTOSAR,A18-0-3,Yes,Required,Automated,Implementation,The library (locale.h) and the setlocale function shall not be used.,,BannedLibraries,Easy, +cpp,AUTOSAR,A18-1-1,Yes,Required,Automated,Implementation,C-style arrays shall not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,A18-1-2,Yes,Required,Automated,Implementation,The std::vector specialization shall not be used.,,BannedTypes,Easy, +cpp,AUTOSAR,A18-1-3,Yes,Required,Automated,Implementation,The std::auto_ptr type shall not be used.,,BannedTypes,Easy, +cpp,AUTOSAR,A18-1-4,Yes,Required,Automated,Implementation,A pointer pointing to an element of an array of objects shall not be passed to a smart pointer of single object type.,,Pointers,Medium, +cpp,AUTOSAR,A18-1-6,Yes,Required,Automated,Implementation,All std::hash specializations for user-defined types shall have a noexcept function call operator.,,OperatorInvariants,Easy, +cpp,AUTOSAR,A18-5-1,Yes,Required,Automated,Implementation,"Functions malloc, calloc, realloc and free shall not be used.",,BannedFunctions,Easy, +cpp,AUTOSAR,A18-5-10,Yes,Required,Automated,Implementation,Placement new shall be used only with properly aligned pointers to sufficient storage capacity.,MEM54-CPP,Allocations,Import, +cpp,AUTOSAR,A18-5-11,Yes,Required,Automated,Implementation,operator new' and 'operator delete' shall be defined together.,DCL54-CPP,Declarations,Easy, +cpp,AUTOSAR,A18-5-2,Yes,Required,Partially Automated,Implementation,Non-placement new or delete expressions shall not be used.,,Allocations,Hard, +cpp,AUTOSAR,A18-5-3,Yes,Required,Automated,Implementation,The form of the delete expression shall match the form of the new expression used to allocate the memory.,cpp/new-free-mismatch?,Freed,Very Hard, +cpp,AUTOSAR,A18-5-4,Yes,Required,Automated,Implementation,"If a project has sized or unsized version of operator 'delete' globally defined, then both sized and unsized versions shall be defined.",,Declarations,Easy, +cpp,AUTOSAR,A18-5-5,Yes,Required,Partially Automated,Toolchain,"Memory management functions shall ensure the following: (a) deterministic behavior resulting with the existence of worst-case execution time, (b) avoiding memory fragmentation, (c) avoid running out of memory, (d) 349 of 510 Document ID 839: AUTOSAR_RS_CPP14Guidelines",,Invariants,Hard, +cpp,AUTOSAR,A18-5-6,Yes,Required,Non-Automated,Verification / Toolchain,"An analysis shall be performed to analyze the failure modes of dynamic memory management. In particular, the following failure modes shall be analyzed: (a) non-deterministic behavior resulting with nonexistence of worst-case execution time, (b) memory fragmentation, (c) running out of memory, (d) mismatched allocations and deallocations, (e) dependence on non-deterministic calls to kernel.",,Allocations,Audit,Produce a list of allocations in the program. +cpp,AUTOSAR,A18-5-7,No,Required,Non-Automated,Implementation,"If non-realtime implementation of dynamic memory management functions is used in the project, then memory shall only be allocated and deallocated during non-realtime program phases.",,,,No specific ideas for implementing this. +cpp,AUTOSAR,A18-5-8,Yes,Required,Partially Automated,Implementation,Objects that do not outlive a function shall have automatic storage duration.,,Allocations,Medium, +cpp,AUTOSAR,A18-5-9,Yes,Required,Automated,Implementation,Custom implementations of dynamic memory allocation and deallocation functions shall meet the semantic requirements specified in the corresponding 'Required behaviour' clause from the C++ Standard.,MEM55-CPP,Allocations,Import, +cpp,AUTOSAR,A18-9-1,Yes,Required,Automated,Implementation,The std::bind shall not be used.,,BannedFunctions,Easy, +cpp,AUTOSAR,A18-9-2,Yes,Required,Automated,Implementation,"Forwarding values to other functions shall be done via: (1) std::move if the value is an rvalue reference, (2) std::forward if the value is forwarding reference.",,MoveForward,Medium, +cpp,AUTOSAR,A18-9-3,Yes,Required,Automated,Implementation,The std::move shall not be used on objects declared const or const&.,,MoveForward,Easy, +cpp,AUTOSAR,A18-9-4,Yes,Required,Automated,Implementation,An argument to std::forward shall not be subsequently used.,,MoveForward,Medium, +cpp,AUTOSAR,A2-10-1,Yes,Required,Automated,Architecture / Design / Implementation,An identifier declared in an inner scope shall not hide an identifier declared in an outer scope.,M2-10-2,Naming,Easy, +cpp,AUTOSAR,A2-10-4,Yes,Required,Automated,Implementation,The identifier name of a non-member object with static storage duration or static function shall not be reused within a namespace.,M2-10-5,Naming,Easy, +cpp,AUTOSAR,A2-10-5,Yes,Advisory,Automated,Design / Implementation,An identifier name of a function with static storage duration or a non-member object with external or internal linkage should not be reused.,M2-10-5,Naming,Easy, +cpp,AUTOSAR,A2-10-6,Yes,Required,Automated,Implementation,"A class or enumeration name shall not be hidden by a variable, function or enumerator declaration in the same scope.",M2-10-6,Naming,Easy, +cpp,AUTOSAR,A2-11-1,Yes,Required,Automated,Design / Implementation,Volatile keyword shall not be used.,cpp/jsf/av-rule-205,BannedSyntax,Easy, +cpp,AUTOSAR,A2-13-1,Yes,Required,Automated,Architecture / Design / Implementation,Only those escape sequences that are defined in ISO/IEC 14882:2014 shall be used.,M2-13-1,Literals,Easy, +cpp,AUTOSAR,A2-13-2,No,Required,Automated,Implementation,String literals with different encoding prefixes shall not be concatenated.,M2-13-5,,,"From the sample, it looks like this is compiler enforced." +cpp,AUTOSAR,A2-13-3,Yes,Required,Automated,Architecture / Design / Implementation,Type wchar_t shall not be used.,,BannedTypes,Easy, +cpp,AUTOSAR,A2-13-4,Yes,Required,Automated,Architecture / Design / Implementation,String literals shall not be assigned to non-constant pointers.,,Strings,Easy, +cpp,AUTOSAR,A2-13-5,Yes,Advisory,Automated,Implementation,Hexadecimal constants should be upper case.,,Literals,Easy, +cpp,AUTOSAR,A2-13-6,Yes,Required,Automated,Architecture / Design / Implementation,Universal character names shall be used only inside character or string literals.,,Naming,Easy, +cpp,AUTOSAR,A2-3-1,Yes,Required,Automated,Architecture / Design / Implementation,Only those characters specified in the C++ Language Standard basic source character set shall be used in the source code.,,Naming,Easy,"We can only provide partial coverage for this rule, because we have a semantic not syntactic model of the code." +cpp,AUTOSAR,A2-5-1,No,Required,Automated,Implementation,Trigraphs shall not be used.,,,,Trigraphs/digraphs are implemented by the preprocessor in a such a way that we may not have that information in our database. We could look for compiler flags here. +cpp,AUTOSAR,A2-5-2,No,Required,Automated,Implementation,Digraphs shall not be used.,,,,Trigraphs/digraphs are implemented by the preprocessor in a such a way that we may not have that information in our database. We could look for compiler flags here. +cpp,AUTOSAR,A2-7-1,Yes,Required,Automated,Implementation,The character \ shall not occur as a last character of a C++ comment.,,Comments,Easy, +cpp,AUTOSAR,A2-7-2,Yes,Required,Non-Automated,Implementation,Sections of code shall not be 'commented out'.,M2-7-2,Comments,Easy,We can write a heuristic query that looks for code markers in comments. +cpp,AUTOSAR,A2-7-3,Yes,Required,Automated,Implementation,"All declarations of 'user-defined' types, static and non-static data members, functions and methods shall be preceded by documentation.",,Comments,Easy, +cpp,AUTOSAR,A2-7-5,No,Required,Non-Automated,Implementation,"Comments shall not document any actions or sources (e.g. tables, figures, paragraphs, etc.) that are outside of the file.",,,,Difficult to ascertain programmatically +cpp,AUTOSAR,A2-8-1,No,Required,Non-Automated,Architecture / Design / Implementation,A header file name should reflect the logical entity for which it provides declarations.,,,,Difficult to ascertain programmatically +cpp,AUTOSAR,A2-8-2,No,Advisory,Non-Automated,Architecture / Design / Implementation,An implementation file name should reflect the logical entity for which it provides definitions.,,,,Difficult to ascertain programmatically +cpp,AUTOSAR,A20-8-1,Yes,Required,Automated,Implementation,An already-owned pointer value shall not be stored in an unrelated smart pointer.,MEM56-CPP,SmartPointers1,Import, +cpp,AUTOSAR,A20-8-2,Yes,Required,Automated,Implementation,A std::unique_ptr shall be used to represent exclusive ownership.,,SmartPointers1,Hard, +cpp,AUTOSAR,A20-8-3,Yes,Required,Automated,Implementation,A std::shared_ptr shall be used to represent shared ownership.,,SmartPointers1,Hard, +cpp,AUTOSAR,A20-8-4,Yes,Required,Automated,Implementation,A std::unique_ptr shall be used over std::shared_ptr if ownership sharing is not required.,,SmartPointers1,Hard, +cpp,AUTOSAR,A20-8-5,Yes,Required,Automated,Implementation,std::make_unique shall be used to construct objects owned by std::unique_ptr.,,SmartPointers1,Easy, +cpp,AUTOSAR,A20-8-6,Yes,Required,Automated,Implementation,std::make_shared shall be used to construct objects owned by std::shared_ptr.,,SmartPointers1,Easy, +cpp,AUTOSAR,A20-8-7,Yes,Required,Non-Automated,Implementation,A std::weak_ptr shall be used to represent temporary shared ownership.,,SmartPointers2,Hard,"We can find some specific cases here: mutual assignment of two variables, for example." +cpp,AUTOSAR,A21-8-1,Yes,Required,Automated,Implementation,Arguments to character-handling functions shall be representable as an unsigned char.,STR37-C,TypeRanges,Hard, +cpp,AUTOSAR,A23-0-1,Yes,Required,Automated,Implementation,An iterator shall not be implicitly converted to const_iterator.,,Iterators,Easy, +cpp,AUTOSAR,A23-0-2,Yes,Required,Automated,Implementation,"Elements of a container shall only be accessed via valid references, iterators, and pointers.",CTR51-CPP,Iterators,Import, +cpp,AUTOSAR,A25-1-1,Yes,Required,Automated,Implementation,Non-static data members or captured values of predicate function objects that are state related to this object's identity shall not be copied.,CTR58-CPP,SideEffects2,Import, +cpp,AUTOSAR,A25-4-1,Yes,Required,Non-Automated,Implementation,Ordering predicates used with associative containers and STL sorting and related algorithms shall adhere to a strict weak ordering relation.,CTR57-CPP,Invariants,Import,Hard to determine in general. Easiest is likely the irreflexivity clause (specifically using std::less_equal and similar library functions) +cpp,AUTOSAR,A26-5-1,Yes,Required,Automated,Implementation,Pseudorandom numbers shall not be generated using std::rand().,MSC50-CPP,BannedFunctions,Import, +cpp,AUTOSAR,A26-5-2,Yes,Required,Automated,Implementation,Random number engines shall not be default-initialized.,MSC51-CPP,Initialization,Easy, +cpp,AUTOSAR,A27-0-1,Yes,Required,Non-Automated,Implementation,Inputs from independent components shall be validated.,,TypeRanges,Medium,"We can perform some checking here assuming: we have annotations which determine the boundaries between components, and the appropriate checks that should be performed." +cpp,AUTOSAR,A27-0-2,Yes,Advisory,Automated,Implementation,A C-style string shall guarantee sufficient space for data and the null terminator.,STR50-CPP,Strings,Import, +cpp,AUTOSAR,A27-0-3,Yes,Required,Automated,Implementation,Alternate input and output operations on a file stream shall not be used without an intervening flush or positioning call.,FIO50-CPP,IO,Import, +cpp,AUTOSAR,A27-0-4,Yes,Required,Automated,Implementation,C-style strings shall not be used.,,Strings,Hard, +cpp,AUTOSAR,A3-1-1,Yes,Required,Automated,Architecture / Design / Implementation,It shall be possible to include any header file in multiple translation units without violating the One Definition Rule.,M3-1-1,Includes,Easy, +cpp,AUTOSAR,A3-1-2,Yes,Required,Automated,Architecture / Design / Implementation,"Header files, that are defined locally in the project, shall have a file name extension of one of: "".h"", "".hpp"" or "".hxx"".",cpp/jsf/av-rule-53,Includes,Easy, +cpp,AUTOSAR,A3-1-3,Yes,Advisory,Automated,Architecture / Design / Implementation,"Implementation files, that are defined locally in the project, should have a file name extension of "".cpp"".",,Includes,Easy, +cpp,AUTOSAR,A3-1-4,Yes,Required,Automated,Design / Implementation,"When an array with external linkage is declared, its size shall be stated explicitly.",M3-1-3,Scope,Easy, +cpp,AUTOSAR,A3-1-5,Yes,Required,Partially-Automated,Design,A function definition shall only be placed in a class definition if (1) the function is intended to be inlined (2) it is a member function template (3) it is a member function of a class template.,,Classes,Medium, +cpp,AUTOSAR,A3-1-6,Yes,Advisory,Automated,Design,Trivial accessor and mutator functions should be inlined.,,Functions,Easy, +cpp,AUTOSAR,A3-3-1,Yes,Required,Automated,Implementation,Objects or functions with external linkage (including members of named namespaces) shall be declared in a header file.,M3-3-1,Includes,Easy, +cpp,AUTOSAR,A3-3-2,Yes,Required,Automated,Implementation,Static and thread-local objects shall be constant-initialized.,DCL56-CPP,Initialization,Medium, +cpp,AUTOSAR,A3-8-1,Yes,Required,Non-Automated,Implementation,An object shall not be accessed outside of its lifetime.,EXP54-CPP,Freed,Import,"A replica of a CERT-CPP rule, there are numerous specific cases we can cover." +cpp,AUTOSAR,A3-9-1,Yes,Required,Automated,Implementation,"Fixed width integer types from , indicating the size and signedness, shall be used in place of the basic numerical types.",M3-9-2,Declarations,Easy, +cpp,AUTOSAR,A4-10-1,Yes,Required,Automated,Architecture / Design / Implementation,Only nullptr literal shall be used as the null-pointer-constant.,,Literals,Easy, +cpp,AUTOSAR,A4-5-1,Yes,Required,Automated,Implementation,"Expressions with type enum or enum class shall not be used as operands to built-in and overloaded operators other than the subscript operator [ ], the assignment operator =, the equality operators == and ! =, the unary & operator, and the relational operators <, <=, >, >=.",M4-5-2,Expressions,Easy, +cpp,AUTOSAR,A4-7-1,Yes,Required,Automated,Implementation,An integer expression shall not lead to data loss.,M5-0-6,IntegerConversion,Very Hard, +cpp,AUTOSAR,A5-0-1,Yes,Required,Automated,Implementation,The value of an expression shall be the same under any order of evaluation that the standard permits.,M5-0-1,OrderOfEvaluation,Hard, +cpp,AUTOSAR,A5-0-2,Yes,Required,Automated,Implementation,The condition of an if-statement and the condition of an iteration statement shall have type bool.,M5-0-13,Conditionals,Easy, +cpp,AUTOSAR,A5-0-3,Yes,Required,Automated,Implementation,The declaration of objects shall contain no more than two levels of pointer indirection.,M5-0-19,Pointers,Easy, +cpp,AUTOSAR,A5-0-4,Yes,Required,Automated,Implementation,Pointer arithmetic shall not be used with pointers to non-final classes.,CTR56-CPP,Pointers,Easy, +cpp,AUTOSAR,A5-1-1,Yes,Required,Partially Automated,Implementation,"Literal values shall not be used apart from type initialization, otherwise symbolic names shall be used instead.",,Literals,Easy, +cpp,AUTOSAR,A5-1-2,Yes,Required,Automated,Implementation,Variables shall not be implicitly captured in a lambda expression.,,Lambdas,Easy, +cpp,AUTOSAR,A5-1-3,Yes,Required,Automated,Implementation,Parameter list (possibly empty) shall be included in every lambda expression.,,Lambdas,Easy, +cpp,AUTOSAR,A5-1-4,Yes,Required,Automated,Implementation,A lambda expression object shall not outlive any of its reference-captured objects.,EXP61-CPP,Lambdas,Import, +cpp,AUTOSAR,A5-1-6,Yes,Advisory,Automated,Implementation,Return type of a non-void return type lambda expression should be explicitly specified.,,Lambdas,Easy, +cpp,AUTOSAR,A5-1-7,Yes,Required,Automated,Implementation,A lambda shall not be an operand to decltype or typeid.,,Lambdas,Easy, +cpp,AUTOSAR,A5-1-8,Yes,Advisory,Automated,Implementation,Lambda expressions should not be defined inside another lambda expression.,,Lambdas,Easy, +cpp,AUTOSAR,A5-1-9,Yes,Advisory,Automated,Implementation,Identical unnamed lambda expressions shall be replaced with a named function or a named lambda expression.,,Lambdas,Very Hard, +cpp,AUTOSAR,A5-10-1,Yes,Required,Automated,Implementation,A pointer to member virtual function shall only be tested for equality with null-pointer-constant.,,Pointers,Medium, +cpp,AUTOSAR,A5-16-1,Yes,Required,Automated,Implementation,The ternary conditional operator shall not be used as a sub-expression.,,BannedSyntax,Easy, +cpp,AUTOSAR,A5-2-1,Yes,Advisory,Automated,Implementation,dynamic_cast should not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,A5-2-2,Yes,Required,Automated,Implementation,Traditional C-style casts shall not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,A5-2-3,Yes,Required,Automated,Implementation,A cast shall not remove any const or volatile qualification from the type of a pointer or reference.,EXP55-CPP,Const,Import, +cpp,AUTOSAR,A5-2-4,Yes,Required,Automated,Implementation,reinterpret_cast shall not be used.,M5-2-7,BannedSyntax,Easy, +cpp,AUTOSAR,A5-2-5,Yes,Required,Automated,Implementation,An array or container shall not be accessed beyond its range.,CTR50-CPP,OutOfBounds,Import, +cpp,AUTOSAR,A5-2-6,Yes,Required,Automated,Implementation,The operands of a logical && or || shall be parenthesized if the operands contain binary operators.,M5-2-1,OrderOfEvaluation,Easy, +cpp,AUTOSAR,A5-3-1,Yes,Required,Non-Automated,Implementation,Evaluation of the operand to the typeid operator shall not contain side effects.,,SideEffects1,Easy,"We will make use of a shared ""side-effects"" library for this query." +cpp,AUTOSAR,A5-3-2,Yes,Required,Partially Automated,Implementation,Null pointers shall not be dereferenced.,,Null,Very Hard, +cpp,AUTOSAR,A5-3-3,Yes,Required,Automated,Implementation,Pointers to incomplete class types shall not be deleted.,EXP57-CPP,Pointers,Easy, +cpp,AUTOSAR,A5-5-1,Yes,Required,Automated,Implementation,A pointer to member shall not access non-existent class members.,OOP55-CPP,Pointers,Import, +cpp,AUTOSAR,A5-6-1,Yes,Required,Automated,Implementation,The right hand operand of the integer division or remainder operators shall not be equal to zero.,,Expressions,Hard, +cpp,AUTOSAR,A6-2-1,Yes,Required,Automated,Implementation,"Move and copy assignment operators shall either move or respectively copy base classes and data members of a class, without any side effects.",,SideEffects2,Hard, +cpp,AUTOSAR,A6-2-2,Yes,Required,Automated,Implementation,Expression statements shall not be explicit calls to constructors of temporary objects only.,,OrderOfEvaluation,Easy, +cpp,AUTOSAR,A6-4-1,Yes,Required,Automated,Implementation,"A switch statement shall have at least two case-clauses, distinct from the default label.",cpp/trivial-switch,Conditionals,Easy, +cpp,AUTOSAR,A6-5-1,Yes,Required,Automated,Implementation,A for-loop that loops through all elements of the container and does not use its loop-counter shall not be used.,,Loops,Easy, +cpp,AUTOSAR,A6-5-2,Yes,Required,Automated,Implementation,A for loop shall contain a single loop-counter which shall not have floating-point type.,M6-5-1,Loops,Easy, +cpp,AUTOSAR,A6-5-3,Yes,Advisory,Automated,Implementation,Do statements should not be used.,,Loops,Easy, +cpp,AUTOSAR,A6-5-4,Yes,Advisory,Automated,Implementation,For-init-statement and expression should not perform actions other than loop-counter initialization and modification.,,Loops,Easy, +cpp,AUTOSAR,A6-6-1,Yes,Required,Automated,Implementation,The goto statement shall not be used.,cpp/jpl-c/simple-control-flow-goto,BannedSyntax,Easy, +cpp,AUTOSAR,A7-1-1,Yes,Required,Automated,Implementation,Constexpr or const specifiers shall be used for immutable data declaration.,,Const,Hard, +cpp,AUTOSAR,A7-1-2,Yes,Required,Automated,Implementation,The constexpr specifier shall be used for values that can be determined at compile time.,,Const,Medium, +cpp,AUTOSAR,A7-1-3,Yes,Required,Automated,Implementation,CV-qualifiers shall be placed on the right hand side of the type that is a typedef or a using name.,,Const,Easy, +cpp,AUTOSAR,A7-1-4,Yes,Required,Automated,Implementation,The register keyword shall not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,A7-1-5,Yes,Required,Automated,Implementation,"The auto specifier shall not be used apart from following cases: (1) to declare that a variable has the same type as return type of a function call, (2) to declare that a variable has the same type as initializer of non-fundamental type, (3) to declare parameters of a generic lambda expression, (4) to declare a function template using trailing return type syntax.",,Declarations,Medium, +cpp,AUTOSAR,A7-1-6,Yes,Required,Automated,Implementation,The typedef specifier shall not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,A7-1-7,Yes,Required,Automated,Implementation,Each expression statement and identifier declaration shall be placed on a separate line.,,Declarations,Easy, +cpp,AUTOSAR,A7-1-8,Yes,Required,Automated,Implementation,A non-type specifier shall be placed before a type specifier in a declaration.,,Declarations,Easy, +cpp,AUTOSAR,A7-1-9,Yes,Required,Automated,Implementation,"A class, structure, or enumeration shall not be declared in the definition of its type.",,Declarations,Easy, +cpp,AUTOSAR,A7-2-1,Yes,Required,Automated,Implementation,An expression with enum underlying type shall only have values corresponding to the enumerators of the enumeration.,M7-2-1,TypeRanges,Hard, +cpp,AUTOSAR,A7-2-2,Yes,Required,Automated,Implementation,Enumeration underlying base type shall be explicitly defined.,,Declarations,Easy, +cpp,AUTOSAR,A7-2-3,Yes,Required,Automated,Implementation,Enumerations shall be declared as scoped enum classes.,,Declarations,Easy, +cpp,AUTOSAR,A7-2-4,Yes,Required,Automated,Implementation,"In an enumeration, either (1) none, (2) the first or (3) all enumerators shall be initialized.",M8-5-3,Declarations,Easy, +cpp,AUTOSAR,A7-2-5,Yes,Advisory,Non-Automated,Design,Enumerations should be used to represent sets of related named constants.,,TypeRanges,Audit,List all enumerations +cpp,AUTOSAR,A7-3-1,Yes,Required,Automated,Implementation,All overloads of a function shall be visible from where it is called.,M7-3-5,Scope,Easy, +cpp,AUTOSAR,A7-4-1,Yes,Required,Automated,Implementation,The asm declaration shall not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,A7-5-1,Yes,Required,Automated,Implementation,A function shall not return a reference or a pointer to a parameter that is passed by reference to const.,,Functions,Easy, +cpp,AUTOSAR,A7-5-2,Yes,Required,Automated,Implementation,"Functions shall not call themselves, either directly or indirectly.",M7-5-4,Functions,Easy, +cpp,AUTOSAR,A7-6-1,Yes,Required,Automated,Implementation,Functions declared with the [[noreturn]] attribute shall not return.,MSC53-CPP,Functions,Import, +cpp,AUTOSAR,A8-2-1,Yes,Required,Automated,Implementation,"When declaring function templates, the trailing return type syntax shall be used if the return type depends on the type of parameters.",,Templates,Easy, +cpp,AUTOSAR,A8-4-1,Yes,Required,Automated,Implementation,Functions shall not be defined using the ellipsis notation.,M8-4-1,BannedSyntax,Easy, +cpp,AUTOSAR,A8-4-10,Yes,Required,Automated,Design,A parameter shall be passed by reference if it can't be NULL,,Null,Hard, +cpp,AUTOSAR,A8-4-11,Yes,Required,Automated,Design,A smart pointer shall only be used as a parameter type if it expresses lifetime semantics,,SmartPointers1,Medium, +cpp,AUTOSAR,A8-4-12,Yes,Required,Automated,Design,A std::unique_ptr shall be passed to a function as: (1) a copy to express the function assumes ownership (2) an lvalue reference to express that the function replaces the managed object.,,SmartPointers1,Medium, +cpp,AUTOSAR,A8-4-13,Yes,Required,Automated,Design,A std::shared_ptr shall be passed to a function as: (1) a copy to express the function shares ownership (2) an lvalue reference to express that the function replaces the managed object (3) a const lvalue reference to express that the function retains a reference count.,,SmartPointers1,Medium, +cpp,AUTOSAR,A8-4-14,No,Required,Non-Automated,Design,Interfaces shall be precisely and strongly typed.,,,,Difficult to ascertain programmatically +cpp,AUTOSAR,A8-4-2,Yes,Required,Automated,Implementation,All exit paths from a function with non-void return type shall have an explicit return statement with an expression.,M8-4-3,Functions,Easy, +cpp,AUTOSAR,A8-4-3,No,Advisory,Non-Automated,Design,Common ways of passing parameters should be used.,,,,The practical parts of this are covered by other rules (such as A8-4-5 to A8-4-9) +cpp,AUTOSAR,A8-4-4,Yes,Advisory,Automated,Design,Multiple output values from a function should be returned as a struct or tuple.,,Functions,Easy, +cpp,AUTOSAR,A8-4-5,Yes,Required,Automated,Design,'consume' parameters declared as X && shall always be moved from.,,MoveForward,Easy, +cpp,AUTOSAR,A8-4-6,Yes,Required,Automated,Design,'forward' parameters declared as T && shall always be forwarded.,,MoveForward,Easy, +cpp,AUTOSAR,A8-4-7,Yes,Required,Automated,Design,'in' parameters for 'cheap to copy' types shall be passed by value.,,Classes,Easy, +cpp,AUTOSAR,A8-4-8,Yes,Required,Automated,Design,Output parameters shall not be used.,,Const,Easy, +cpp,AUTOSAR,A8-4-9,Yes,Required,Automated,Design,'in-out' parameters declared as T & shall be modified.,,Const,Medium, +cpp,AUTOSAR,A8-5-0,Yes,Required,Automated,Implementation,All memory shall be initialized before it is read.,M8-5-1,Uninitialized,Very Hard, +cpp,AUTOSAR,A8-5-1,Yes,Required,Automated,Implementation,"In an initialization list, the order of initialization shall be following: (1) virtual base classes in depth and left to right order of the inheritance graph, (2) direct base classes in left to right order of inheritance list, (3) non-static data members in the order they were declared in the class definition.",,Initialization,Easy, +cpp,AUTOSAR,A8-5-2,Yes,Required,Automated,Implementation,"Braced-initialization {}, without equals sign, shall be used for variable initialization.",,Initialization,Easy, +cpp,AUTOSAR,A8-5-3,Yes,Required,Automated,Implementation,A variable of type auto shall not be initialized using {} or ={} braced-initialization.,,Initialization,Easy, +cpp,AUTOSAR,A8-5-4,Yes,Advisory,Automated,Implementation,"If a class has a user-declared constructor that takes a parameter of type std::initializer_list, then it shall be the only constructor apart from special member function constructors.",,Initialization,Easy, +cpp,AUTOSAR,A9-3-1,Yes,Required,Partially Automated,Implementation,Member functions shall not return non-const 'raw' pointers or references to private or protected data owned by the class.,M9-3-2,Classes,Hard, +cpp,AUTOSAR,A9-5-1,Yes,Required,Automated,Implementation,Unions shall not be used.,M9-5-1,BannedSyntax,Easy, +cpp,AUTOSAR,A9-6-1,Yes,Required,Partially Automated,Design,"Data types used for interfacing with hardware or conforming to communication protocols shall be trivial, standard-layout and only contain members of types with defined sizes.",,Classes,Medium, +cpp,AUTOSAR,A9-6-2,Yes,Required,Non-Automated,Design,Bit-fields shall be used only when interfacing to hardware or conforming to communication protocols.,,Representation,Audit,Produce an audit list. Omit items from the audit list which have an appropriate annotation. +cpp,AUTOSAR,M0-1-1,Yes,Required,Automated,Implementation,A project shall not contain unreachable code.,cpp/jsf/av-rule-186,DeadCode,Easy, +cpp,AUTOSAR,M0-1-10,Yes,Advisory,Automated,Implementation,Every defined function should be called at least once.,cpp/unused-static-function,DeadCode,Easy, +cpp,AUTOSAR,M0-1-2,Yes,Required,Automated,Implementation,A project shall not contain infeasible paths.,,DeadCode,Very Hard, +cpp,AUTOSAR,M0-1-3,Yes,Required,Automated,Implementation,A project shall not contain unused variables.,cpp/unused-static-variable and ,DeadCode,Easy, +cpp,AUTOSAR,M0-1-4,Yes,Required,Automated,Implementation,A project shall not contain non-volatile POD variables having only one use.,,DeadCode,Easy, +cpp,AUTOSAR,M0-1-8,Yes,Required,Automated,Implementation,All functions with void return type shall have external side effect(s).,,SideEffects2,Medium, +cpp,AUTOSAR,M0-1-9,Yes,Required,Automated,Implementation,There shall be no dead code.,cpp/dead-code-condition???,DeadCode,Medium, +cpp,AUTOSAR,M0-2-1,Yes,Required,Automated,Implementation,An object shall not be assigned to an overlapping object.,,Representation,Hard, +cpp,AUTOSAR,M0-3-1,No,Required,Non-Automated,Implementation / Verification,Minimization of run-time failures shall be ensured by the use of at least one of: (a) static analysis tools/techniques; (b) dynamic analysis tools/techniques; (c) explicit coding of checks to handle run-time faults.,,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,M0-3-2,Yes,Required,Non-Automated,Implementation,"If a function generates error information, then that error information shall be tested.",cpp/jpl-c/checking-return-values???,Expressions,Medium,"We can identify certain common error cases (return value, return parameter, global parameter) and confirm they have been checked." +cpp,AUTOSAR,M0-4-1,No,Required,Non-Automated,Implementation,Use of scaled-integer or fixed-point arithmetic shall be documented.,,,,Documentation not covered by queries +cpp,AUTOSAR,M0-4-2,No,Required,Non-Automated,Implementation,Use of floating-point arithmetic shall be documented.,,,,Documentation not covered by queries +cpp,AUTOSAR,M1-0-2,No,Required,Non-Automated,Toolchain,"Multiple compilers shall only be used if they have a common, defined interface.",,,,Allocated target not covered by CodeQL +cpp,AUTOSAR,M10-1-1,Yes,Advisory,Automated,Implementation,Classes should not be derived from virtual bases.,,Inheritance,Easy, +cpp,AUTOSAR,M10-1-2,Yes,Required,Automated,Implementation,A base class shall only be declared virtual if it is used in a diamond hierarchy.,,Inheritance,Easy, +cpp,AUTOSAR,M10-1-3,Yes,Required,Automated,Implementation,An accessible base class shall not be both virtual and non-virtual in the same hierarchy.,,Inheritance,Easy, +cpp,AUTOSAR,M10-2-1,Yes,Advisory,Automated,Implementation,All accessible entity names within a multiple inheritance hierarchy should be unique.,,Inheritance,Easy, +cpp,AUTOSAR,M10-3-3,Yes,Required,Automated,Implementation,A virtual function shall only be overridden by a pure virtual function if it is itself declared as pure virtual.,,VirtualFunctions,Easy, +cpp,AUTOSAR,M11-0-1,Yes,Required,Automated,Implementation,Member data in non-POD class types shall be private.,,Classes,Easy, +cpp,AUTOSAR,M12-1-1,Yes,Required,Automated,Implementation,An object's dynamic type shall not be used from the body of its constructor or destructor.,,Inheritance,Easy, +cpp,AUTOSAR,M14-5-3,Yes,Required,Automated,Implementation,A copy assignment operator shall be declared when there is a template assignment operator with a parameter that is a generic parameter.,,Templates,Easy, +cpp,AUTOSAR,M14-6-1,Yes,Required,Automated,Implementation,"In a class template with a dependent base, any name that may be found in that dependent base shall be referred to using a qualified-id or this->.",,Templates,Easy, +cpp,AUTOSAR,M15-0-3,Yes,Required,Automated,Implementation,Control shall not be transferred into a try or catch block using a goto or a switch statement.,,Exceptions1,Easy, +cpp,AUTOSAR,M15-1-1,Yes,Required,Automated,Implementation,The assignment-expression of a throw statement shall not itself cause an exception to be thrown.,,Exceptions1,Easy, +cpp,AUTOSAR,M15-1-2,Yes,Required,Automated,Implementation,NULL shall not be thrown explicitly.,,Exceptions1,Easy, +cpp,AUTOSAR,M15-1-3,Yes,Required,Automated,Implementation,An empty throw (throw;) shall only be used in the compound statement of a catch handler.,,Exceptions1,Easy, +cpp,AUTOSAR,M15-3-1,Yes,Required,Automated,Implementation,Exceptions shall be raised only after start-up and before termination.,,Exceptions2,Easy, +cpp,AUTOSAR,M15-3-3,Yes,Required,Automated,Implementation,Handlers of a function-try-block implementation of a class constructor or destructor shall not reference non-static members from this class or its bases.,ERR53-CPP,Exceptions2,Import, +cpp,AUTOSAR,M15-3-4,Yes,Required,Automated,Implementation,Each exception explicitly thrown in the code shall have a handler of a compatible type in all call paths that could lead to that point.,,Exceptions1,Medium, +cpp,AUTOSAR,M15-3-6,Yes,Required,Automated,Implementation,"Where multiple handlers are provided in a single try-catch statement or function-try-block for a derived class and some or all of its bases, the handlers shall be ordered most-derived to base class.",ERR54-CPP,Exceptions2,Import, +cpp,AUTOSAR,M15-3-7,Yes,Required,Automated,Implementation,"Where multiple handlers are provided in a single try-catch statement or function-try-block, any ellipsis (catch-all) handler shall occur last.",,Exceptions1,Easy, +cpp,AUTOSAR,M16-0-1,Yes,Required,Automated,Implementation,#include directives in a file shall only be preceded by other pre-processor directives or comments.,cpp/jpl-c/includes-first,Macros,Easy, +cpp,AUTOSAR,M16-0-2,Yes,Required,Automated,Implementation,Macros shall only be #define'd or #undef'd in the global namespace.,,Macros,Easy, +cpp,AUTOSAR,M16-0-5,Yes,Required,Automated,Implementation,Arguments to a function-like macro shall not contain tokens that look like pre-processing directives.,,Macros,Easy, +cpp,AUTOSAR,M16-0-6,Yes,Required,Automated,Implementation,"In the definition of a function-like macro, each instance of a parameter shall be enclosed in parentheses, unless it is used as the operand of # or ##.",,Macros,Easy, +cpp,AUTOSAR,M16-0-7,Yes,Required,Automated,Implementation,"Undefined macro identifiers shall not be used in #if or #elif pre-processor directives, except as operands to the defined operator.",,Macros,Hard, +cpp,AUTOSAR,M16-0-8,No,Required,Automated,Implementation,"If the # token appears as the first token on a line, then it shall be immediately followed by a pre-processing token.",,,,This is verified by the compiler in the cases where the token is not within an ifdef branch that's never taken +cpp,AUTOSAR,M16-1-1,Yes,Required,Automated,Implementation,The defined pre-processor operator shall only be used in one of the two standard forms.,,Macros,Easy, +cpp,AUTOSAR,M16-1-2,No,Required,Automated,Implementation,"All #else, #elif and #endif pre-processor directives shall reside in the same file as the #if or #ifdef directive to which they are related.",,,,Compilers already prohibit this case +cpp,AUTOSAR,M16-2-3,Yes,Required,Automated,Implementation,Include guards shall be provided.,cpp/missing-header-guard,Includes,Easy, +cpp,AUTOSAR,M16-3-1,Yes,Required,Automated,Implementation,There shall be at most one occurrence of the # or ## operators in a single macro definition.,,Macros,Easy, +cpp,AUTOSAR,M16-3-2,Yes,Advisory,Automated,Implementation,The # and ## operators should not be used.,,Macros,Easy, +cpp,AUTOSAR,M17-0-2,Yes,Required,Automated,Implementation,The names of standard library macros and objects shall not be reused.,,Naming,Medium, +cpp,AUTOSAR,M17-0-3,Yes,Required,Automated,Implementation,The names of standard library functions shall not be overridden.,,Naming,Medium, +cpp,AUTOSAR,M17-0-5,Yes,Required,Automated,Implementation,The setjmp macro and the longjmp function shall not be used.,ERR52-CPP,BannedFunctions,Import, +cpp,AUTOSAR,M18-0-3,Yes,Required,Automated,Implementation,"The library functions abort, exit, getenv and system from library shall not be used.",,BannedFunctions,Easy, +cpp,AUTOSAR,M18-0-4,Yes,Required,Automated,Implementation,The time handling functions of library shall not be used.,,BannedFunctions,Easy, +cpp,AUTOSAR,M18-0-5,Yes,Required,Automated,Implementation,The unbounded functions of library shall not be used.,,BannedFunctions,Easy, +cpp,AUTOSAR,M18-2-1,Yes,Required,Automated,Implementation,The macro offsetof shall not be used.,,BannedFunctions,Easy, +cpp,AUTOSAR,M18-7-1,Yes,Required,Automated,Implementation,The signal handling facilities of shall not be used.,,BannedLibraries,Easy, +cpp,AUTOSAR,M19-3-1,Yes,Required,Automated,Implementation,The error indicator errno shall not be used.,,BannedLibraries,Easy, +cpp,AUTOSAR,M2-10-1,Yes,Required,Automated,Architecture / Design / Implementation,Different identifiers shall be typographically unambiguous.,,Naming,Easy, +cpp,AUTOSAR,M2-13-2,Yes,Required,Automated,Architecture / Design / Implementation,Octal constants (other than zero) and octal escape sequences (other than '\0' ) shall not be used.,,Literals,Easy, +cpp,AUTOSAR,M2-13-3,Yes,Required,Automated,Architecture / Design / Implementation,A 'U' suffix shall be applied to all octal or hexadecimal integer literals of unsigned type.,,Literals,Easy, +cpp,AUTOSAR,M2-13-4,Yes,Required,Automated,Architecture / Design / Implementation,Literal suffixes shall be upper case.,,Literals,Easy, +cpp,AUTOSAR,M2-7-1,Yes,Required,Automated,Implementation,The character sequence /* shall not be used within a C-style comment.,,Comments,Easy, +cpp,AUTOSAR,M27-0-1,Yes,Required,Automated,Implementation,The stream input/output library shall not be used.,,BannedLibraries,Easy, +cpp,AUTOSAR,M3-1-2,Yes,Required,Automated,Implementation,Functions shall not be declared at block scope.,,Declarations,Easy, +cpp,AUTOSAR,M3-2-1,Yes,Required,Automated,Implementation,All declarations of an object or function shall have compatible types.,,Declarations,Easy, +cpp,AUTOSAR,M3-2-2,Yes,Required,Automated,Implementation,The One Definition Rule shall not be violated.,DCL60-CPP,Scope,Import, +cpp,AUTOSAR,M3-2-3,Yes,Required,Automated,Implementation,"A type, object or function that is used in multiple translation units shall be declared in one and only one file.",,Scope,Easy, +cpp,AUTOSAR,M3-2-4,Yes,Required,Automated,Implementation,An identifier with external linkage shall have exactly one definition.,,Scope,Easy, +cpp,AUTOSAR,M3-3-2,Yes,Required,Automated,Implementation,If a function has internal linkage then all re-declarations shall include the static storage class specifier.,,Scope,Easy, +cpp,AUTOSAR,M3-4-1,Yes,Required,Automated,Implementation,An identifier declared to be an object or type shall be defined in a block that minimizes its visibility.,,Scope,Easy, +cpp,AUTOSAR,M3-9-1,Yes,Required,Automated,Implementation,"The types used for an object, a function return type, or a function parameter shall be token-for-token identical in all declarations and re-declarations.",M8-4-2,Declarations,Easy, +cpp,AUTOSAR,M3-9-3,Yes,Required,Automated,Implementation,The underlying bit representations of floating-point values shall not be used.,,Representation,Easy, +cpp,AUTOSAR,M4-10-1,Yes,Required,Automated,Implementation,NULL shall not be used as an integer value.,,Literals,Easy, +cpp,AUTOSAR,M4-10-2,Yes,Required,Automated,Implementation,Literal zero (0) shall not be used as the null-pointer-constant.,A4-10-1,Literals,Easy, +cpp,AUTOSAR,M4-5-1,Yes,Required,Automated,Implementation,"Expressions with type bool shall not be used as operands to built-in operators other than the assignment operator =, the logical operators",,Expressions,Easy, +cpp,AUTOSAR,M4-5-3,Yes,Required,Automated,Implementation,"Expressions with type (plain) char and wchar_t shall not be used as operands to built-in operators other than the assignment operator =, the equality operators == and ! =, and the unary & operator.",,Expressions,Easy, +cpp,AUTOSAR,M5-0-10,Yes,Required,Automated,Implementation,"If the bitwise operators ~and << are applied to an operand with an underlying type of unsigned char or unsigned short, the result shall be immediately cast to the underlying type of the operand.",,Operators,Easy, +cpp,AUTOSAR,M5-0-11,Yes,Required,Automated,Implementation,The plain char type shall only be used for the storage and use of character values.,CMISRA-6-01,Strings,Easy, +cpp,AUTOSAR,M5-0-12,Yes,Required,Automated,Implementation,Signed char and unsigned char type shall only be used for the storage and use of numeric values.,CMISRA-6-02,Strings,Easy, +cpp,AUTOSAR,M5-0-14,Yes,Required,Automated,Implementation,The first operand of a conditional-operator shall have type bool.,,Expressions,Easy, +cpp,AUTOSAR,M5-0-15,Yes,Required,Automated,Implementation,Array indexing shall be the only form of pointer arithmetic.,cpp/jsf/av-rule-215?,Pointers,Easy, +cpp,AUTOSAR,M5-0-16,Yes,Required,Automated,Implementation,A pointer operand and any pointer resulting from pointer arithmetic using that operand shall both address elements of the same array.,CTR50-CPP,Pointers,Hard, +cpp,AUTOSAR,M5-0-17,Yes,Required,Automated,Implementation,Subtraction between pointers shall only be applied to pointers that address elements of the same array.,,Pointers,Easy, +cpp,AUTOSAR,M5-0-18,Yes,Required,Automated,Implementation,">, >=, <, <= shall not be applied to objects of pointer type, except where they point to the same array.",,Pointers,Easy, +cpp,AUTOSAR,M5-0-2,Yes,Advisory,Partially Automated,Implementation,Limited dependence should be placed on C++ operator precedence rules in expressions.,,OrderOfEvaluation,Easy, +cpp,AUTOSAR,M5-0-20,Yes,Required,Automated,Implementation,Non-constant operands to a binary bitwise operator shall have the same underlying type.,,Expressions,Easy, +cpp,AUTOSAR,M5-0-21,Yes,Required,Automated,Implementation,Bitwise operators shall only be applied to operands of unsigned underlying type.,,Expressions,Easy, +cpp,AUTOSAR,M5-0-3,Yes,Required,Automated,Implementation,A cvalue expression shall not be implicitly converted to a different underlying type.,,Expressions,Easy, +cpp,AUTOSAR,M5-0-4,Yes,Required,Automated,Implementation,An implicit integral conversion shall not change the signedness of the underlying type.,,IntegerConversion,Easy, +cpp,AUTOSAR,M5-0-5,Yes,Required,Automated,Implementation,There shall be no implicit floating-integral conversions.,,IntegerConversion,Easy, +cpp,AUTOSAR,M5-0-6,Yes,Required,Automated,Implementation,An implicit integral or floating-point conversion shall not reduce the size of the underlying type.,,IntegerConversion,Easy, +cpp,AUTOSAR,M5-0-7,Yes,Required,Automated,Implementation,There shall be no explicit floating-integral conversions of a cvalue expression.,,IntegerConversion,Easy, +cpp,AUTOSAR,M5-0-8,Yes,Required,Automated,Implementation,An explicit integral or floating-point conversion shall not increase the size of the underlying type of a cvalue expression.,,IntegerConversion,Easy, +cpp,AUTOSAR,M5-0-9,Yes,Required,Automated,Implementation,An explicit integral conversion shall not change the signedness of the underlying type of a cvalue expression.,,IntegerConversion,Easy, +cpp,AUTOSAR,M5-14-1,Yes,Required,Automated,Implementation,"The right hand operand of a logical &&, || operators shall not contain side effects.",,SideEffects1,Medium, +cpp,AUTOSAR,M5-17-1,Yes,Required,Non-Automated,Implementation,The semantic equivalence between a binary operator and its assignment operator form shall be preserved.,,OperatorInvariants,Audit,Produce a list of binary and assigment operator pairs. +cpp,AUTOSAR,M5-18-1,Yes,Required,Automated,Implementation,The comma operator shall not be used.,cpp/jsf/av-rule-168,BannedSyntax,Easy, +cpp,AUTOSAR,M5-19-1,Yes,Required,Automated,Implementation,Evaluation of constant unsigned integer expressions shall not lead to wrap-around.,,Expressions,Medium, +cpp,AUTOSAR,M5-2-10,Yes,Required,Automated,Implementation,The increment (++) and decrement (--) operators shall not be mixed with other operators in an expression.,,OrderOfEvaluation,Easy, +cpp,AUTOSAR,M5-2-11,Yes,Required,Automated,Implementation,"The comma operator, && operator and the || operator shall not be overloaded.",,Operators,Easy, +cpp,AUTOSAR,M5-2-12,Yes,Required,Automated,Implementation,An identifier with array type passed as a function argument shall not decay to a pointer.,,Pointers,Easy, +cpp,AUTOSAR,M5-2-2,Yes,Required,Automated,Implementation,A pointer to a virtual base class shall only be cast to a pointer to a derived class by means of dynamic_cast.,,Pointers,Easy, +cpp,AUTOSAR,M5-2-3,Yes,Advisory,Automated,Implementation,Casts from a base class to a derived class should not be performed on polymorphic types.,,Inheritance,Easy, +cpp,AUTOSAR,M5-2-6,Yes,Required,Automated,Implementation,"A cast shall not convert a pointer to a function to any other pointer type, including a pointer to function type.",,Pointers,Easy, +cpp,AUTOSAR,M5-2-8,Yes,Required,Automated,Implementation,An object with integer type or pointer to void type shall not be converted to an object with pointer type.,,Pointers,Easy, +cpp,AUTOSAR,M5-2-9,Yes,Required,Automated,Implementation,A cast shall not convert a pointer type to an integral type.,,Pointers,Easy, +cpp,AUTOSAR,M5-3-1,Yes,Required,Automated,Implementation,"Each operand of the ! operator, the logical && or the logical || operators shall have type bool.",,Operators,Easy, +cpp,AUTOSAR,M5-3-2,Yes,Required,Automated,Implementation,The unary minus operator shall not be applied to an expression whose underlying type is unsigned.,,Operators,Easy, +cpp,AUTOSAR,M5-3-3,Yes,Required,Automated,Implementation,The unary & operator shall not be overloaded.,,Operators,Easy, +cpp,AUTOSAR,M5-3-4,Yes,Required,Automated,Implementation,Evaluation of the operand to the sizeof operator shall not contain side effects.,cpp/sizeof-side-effect,SideEffects1,Easy, +cpp,AUTOSAR,M5-8-1,Yes,Required,Partially Automated,Implementation,The right hand operand of a shift operator shall lie between zero and one less than the width in bits of the underlying type of the left hand operand.,,Expressions,Medium, +cpp,AUTOSAR,M6-2-1,Yes,Required,Automated,Implementation,Assignment operators shall not be used in sub-expressions.,,OrderOfEvaluation,Easy, +cpp,AUTOSAR,M6-2-2,Yes,Required,Partially Automated,Implementation,Floating-point expressions shall not be directly or indirectly tested for equality or inequality.,,Expressions,Easy, +cpp,AUTOSAR,M6-2-3,Yes,Required,Automated,Implementation,"Before preprocessing, a null statement shall only occur on a line by itself; it may be followed by a comment, provided that the first character following the null statement is a white-space character.",,Comments,Easy, +cpp,AUTOSAR,M6-3-1,Yes,Required,Automated,Implementation,"The statement forming the body of a switch, while, do ... while or for statement shall be a compound statement.",,Conditionals,Easy, +cpp,AUTOSAR,M6-4-1,Yes,Required,Automated,Implementation,"An if ( condition ) construct shall be followed by a compound statement. The else keyword shall be followed by either a compound statement, or another if statement.",,Conditionals,Easy, +cpp,AUTOSAR,M6-4-2,Yes,Required,Automated,Implementation,All if ... else if constructs shall be terminated with an else clause.,,Conditionals,Easy, +cpp,AUTOSAR,M6-4-3,Yes,Required,Automated,Implementation,A switch statement shall be a well-formed switch statement.,,Conditionals,Easy, +cpp,AUTOSAR,M6-4-4,Yes,Required,Automated,Implementation,A switch-label shall only be used when the most closely-enclosing compound statement is the body of a switch statement.,,Conditionals,Easy, +cpp,AUTOSAR,M6-4-5,Yes,Required,Automated,Implementation,An unconditional throw or break statement shall terminate every non-empty switch-clause.,cpp/jsf/av-rule-193,Conditionals,Easy, +cpp,AUTOSAR,M6-4-6,Yes,Required,Automated,Implementation,The final clause of a switch statement shall be the default-clause.,,Conditionals,Easy, +cpp,AUTOSAR,M6-4-7,Yes,Required,Automated,Implementation,The condition of a switch statement shall not have bool type.,,Conditionals,Easy, +cpp,AUTOSAR,M6-5-2,Yes,Required,Automated,Implementation,"If loop-counter is not modified by or ++, then, within condition, the loop-counter shall only be used as an operand to <=, <, > or >=.",,Loops,Easy, +cpp,AUTOSAR,M6-5-3,Yes,Required,Automated,Implementation,The loop-counter shall not be modified within condition or statement.,,Loops,Easy, +cpp,AUTOSAR,M6-5-4,Yes,Required,Automated,Implementation,"The loop-counter shall be modified by one of: , ++, = n, or + = n; where n remains constant for the duration of the loop.",,Loops,Easy, +cpp,AUTOSAR,M6-5-5,Yes,Required,Automated,Implementation,A loop-control-variable other than the loop-counter shall not be modified within condition or expression.,,Loops,Easy, +cpp,AUTOSAR,M6-5-6,Yes,Required,Automated,Implementation,A loop-control-variable other than the loop-counter which is modified in statement shall have type bool.,,Loops,Easy, +cpp,AUTOSAR,M6-6-1,Yes,Required,Automated,Implementation,"Any label referenced by a goto statement shall be declared in the same block, or in a block enclosing the goto statement.",,Conditionals,Easy, +cpp,AUTOSAR,M6-6-2,Yes,Required,Automated,Implementation,The goto statement shall jump to a label declared later in the same function body.,,Conditionals,Easy, +cpp,AUTOSAR,M6-6-3,Yes,Required,Automated,Implementation,The continue statement shall only be used within a well-formed for loop.,,Conditionals,Easy, +cpp,AUTOSAR,M7-1-2,Yes,Required,Automated,Implementation,A pointer or reference parameter in a function shall be declared as pointer to const or reference to const if the corresponding object is not modified.,,Const,Hard, +cpp,AUTOSAR,M7-3-1,Yes,Required,Automated,Implementation,"The global namespace shall only contain main, namespace declarations and extern ""C"" declarations.",,Scope,Easy, +cpp,AUTOSAR,M7-3-2,Yes,Required,Automated,Implementation,The identifier main shall not be used for a function other than the global function main.,,Naming,Easy, +cpp,AUTOSAR,M7-3-3,Yes,Required,Automated,Implementation,There shall be no unnamed namespaces in header files.,,Naming,Easy, +cpp,AUTOSAR,M7-3-4,Yes,Required,Automated,Implementation,Using-directives shall not be used.,,BannedSyntax,Easy, +cpp,AUTOSAR,M7-3-6,Yes,Required,Automated,Implementation,Using-directives and using-declarations (excluding class scope or function scope using-declarations) shall not be used in header files.,,BannedSyntax,Easy, +cpp,AUTOSAR,M7-4-1,Yes,Required,Non-Automated,Implementation,All usage of assembler shall be documented.,,BannedLibraries,Audit,List all the places where assembler is used. +cpp,AUTOSAR,M7-4-2,Yes,Required,Automated,Implementation,Assembler instructions shall only be introduced using the asm declaration.,A7-4-1,Functions,Easy, +cpp,AUTOSAR,M7-4-3,Yes,Required,Automated,Implementation,Assembly language shall be encapsulated and isolated.,,Functions,Easy, +cpp,AUTOSAR,M7-5-1,Yes,Required,Non-Automated,Implementation,"A function shall not return a reference or a pointer to an automatic variable (including parameters), defined within the function.",,Functions,Medium,Similar to M7-5-2. +cpp,AUTOSAR,M7-5-2,Yes,Required,Non-Automated,Implementation,The address of an object with automatic storage shall not be assigned to another object that may persist after the first object has ceased to exist.,EXP54-CPP,Freed,Hard,Identify address of expressions for automatic storage objects which flow (via data flow) to some expression which escapes. +cpp,AUTOSAR,M8-0-1,Yes,Required,Automated,Implementation,An init-declarator-list or a member-declarator-list shall consist of a single init-declarator or member-declarator respectively.,,Initialization,Easy, +cpp,AUTOSAR,M8-3-1,Yes,Required,Automated,Implementation,"Parameters in an overriding virtual function shall either use the same default arguments as the function they override, or else shall not specify any default arguments.",,VirtualFunctions,Easy, +cpp,AUTOSAR,M8-4-2,Yes,Required,Automated,Implementation,The identifiers used for the parameters in a re-declaration of a function shall be identical to those in the declaration.,M3-9-1,Naming,Easy, +cpp,AUTOSAR,M8-4-4,Yes,Required,Automated,Implementation,A function identifier shall either be used to call the function or it shall be preceded by &.,,Functions,Easy, +cpp,AUTOSAR,M8-5-2,Yes,Required,Automated,Implementation,Braces shall be used to indicate and match the structure in the non-zero initialization of arrays and structures.,,Initialization,Easy, +cpp,AUTOSAR,M9-3-1,Yes,Required,Automated,Implementation,Const member functions shall not return non-const pointers or references to class-data.,,Const,Easy, +cpp,AUTOSAR,M9-3-3,Yes,Required,Automated,Implementation,"If a member function can be made static then it shall be made static, otherwise if it can be made const then it shall be made const.",,Const,Easy, +cpp,AUTOSAR,M9-6-1,No,Required,Non-Automated,Implementation,"When the absolute positioning of bits representing a bit-field is required, then the behavior and packing of bit-fields shall be documented.",,,,Documentation not covered by queries +cpp,AUTOSAR,M9-6-4,Yes,Required,Automated,Implementation,Named bit-fields with signed integer type shall have a length of more than one bit.,,Representation,Easy, +cpp,CERT-C++,CON50-CPP,Yes,Rule,,,Do not destroy a mutex while it is locked,,Concurrency,Hard, +cpp,CERT-C++,CON51-CPP,Yes,Rule,,,Ensure actively held locks are released on exceptional conditions,,Concurrency,Easy, +cpp,CERT-C++,CON52-CPP,Yes,Rule,,,Prevent data races when accessing bit-fields from multiple threads,,Concurrency,Medium, +cpp,CERT-C++,CON53-CPP,Yes,Rule,,,Avoid deadlock by locking in a predefined order,,Concurrency,Very Hard, +cpp,CERT-C++,CON54-CPP,Yes,Rule,,,Wrap functions that can spuriously wake up in a loop,,Concurrency,Medium, +cpp,CERT-C++,CON55-CPP,Yes,Rule,,,Preserve thread safety and liveness when using condition variables,,Concurrency,Hard, +cpp,CERT-C++,CON56-CPP,Yes,Rule,,,Do not speculatively lock a non-recursive mutex that is already owned by the calling thread,cpp/twice-locked???,Concurrency,Hard, +cpp,CERT-C++,CTR50-CPP,Yes,Rule,,,Guarantee that container indices and iterators are within the valid range,,OutOfBounds,Very Hard, +cpp,CERT-C++,CTR51-CPP,Yes,Rule,,,"Use valid references, pointers, and iterators to reference elements of a container",,Iterators,Hard, +cpp,CERT-C++,CTR52-CPP,Yes,Rule,,,Guarantee that library functions do not overflow,,OutOfBounds,Very Hard, +cpp,CERT-C++,CTR53-CPP,Yes,Rule,,,Use valid iterator ranges,,Iterators,Hard, +cpp,CERT-C++,CTR54-CPP,Yes,Rule,,,Do not subtract iterators that do not refer to the same container,,Iterators,Hard, +cpp,CERT-C++,CTR55-CPP,Yes,Rule,,,Do not use an additive operator on an iterator if the result would overflow,,Iterators,Hard, +cpp,CERT-C++,CTR56-CPP,Yes,Rule,,,Do not use pointer arithmetic on polymorphic objects,,Pointers,Easy, +cpp,CERT-C++,CTR57-CPP,Yes,Rule,,,Provide a valid ordering predicate,,Invariants,Medium, +cpp,CERT-C++,CTR58-CPP,Yes,Rule,,,Predicate function objects should not be mutable,,SideEffects2,Medium, +cpp,CERT-C++,DCL50-CPP,Yes,Rule,,,Do not define a C-style variadic function,,BannedSyntax,Easy, +cpp,CERT-C++,DCL51-CPP,Yes,Rule,,,Do not declare or define a reserved identifier,,Naming,Medium, +cpp,CERT-C++,DCL52-CPP,No,Rule,,,Never qualify a reference type with const or volatile,,,,"This is compiler checked - clang reports an error. The extractor accepts it, but doesn't include the cv information." +cpp,CERT-C++,DCL53-CPP,Yes,Rule,,,Do not write syntactically ambiguous declarations,,Scope,Medium, +cpp,CERT-C++,DCL54-CPP,Yes,Rule,,,Overload allocation and deallocation functions as a pair in the same scope,,Scope,Easy, +cpp,CERT-C++,DCL55-CPP,Yes,Rule,,,Avoid information leakage when passing a class object across a trust boundary,,Uninitialized,Very Hard, +cpp,CERT-C++,DCL56-CPP,Yes,Rule,,,Avoid cycles during initialization of static objects,,Initialization,Easy, +cpp,CERT-C++,DCL57-CPP,Yes,Rule,,,Do not let exceptions escape from destructors or deallocation functions,A15-5-1,Exceptions2,Easy, +cpp,CERT-C++,DCL58-CPP,Yes,Rule,,,Do not modify the standard namespaces,,Scope,Easy, +cpp,CERT-C++,DCL59-CPP,Yes,Rule,,,Do not define an unnamed namespace in a header file,,Scope,Easy, +cpp,CERT-C++,DCL60-CPP,Yes,Rule,,,Obey the one-definition rule,M3-2-2,Scope,Easy, +cpp,CERT-C++,ERR50-CPP,Yes,Rule,,,Do not abruptly terminate the program,,Exceptions1,Medium, +cpp,CERT-C++,ERR51-CPP,Yes,Rule,,,Handle all exceptions,,Exceptions1,Easy, +cpp,CERT-C++,ERR52-CPP,Yes,Rule,,,Do not use setjmp() or longjmp(),cpp/jsf/av-rule-20,BannedFunctions,Easy, +cpp,CERT-C++,ERR53-CPP,Yes,Rule,,,Do not reference base classes or class data members in a constructor or destructor function-try-block handler,,Exceptions1,Easy, +cpp,CERT-C++,ERR54-CPP,Yes,Rule,,,Catch handlers should order their parameter types from most derived to least derived,,Exceptions2,Easy, +cpp,CERT-C++,ERR55-CPP,Yes,Rule,,,Honor exception specifications,A15-4-2,Exceptions1,Medium, +cpp,CERT-C++,ERR56-CPP,Yes,Rule,,,Guarantee exception safety,,ExceptionSafety,Hard, +cpp,CERT-C++,ERR57-CPP,Yes,Rule,,,Do not leak resources when handling exceptions,,ExceptionSafety,Hard, +cpp,CERT-C++,ERR58-CPP,Yes,Rule,,,Handle all exceptions thrown before main() begins executing,,Exceptions1,Easy, +cpp,CERT-C++,ERR59-CPP,Yes,Rule,,,Do not throw an exception across execution boundaries,,TrustBoundaries,Hard, +cpp,CERT-C++,ERR60-CPP,Yes,Rule,,,Exception objects must be nothrow copy constructible,,Exceptions1,Medium, +cpp,CERT-C++,ERR61-CPP,Yes,Rule,,,Catch exceptions by lvalue reference,,Exceptions1,Easy, +cpp,CERT-C++,ERR62-CPP,Yes,Rule,,,Detect errors when converting a string to a number,A18-0-2,TypeRanges,Medium, +cpp,CERT-C++,EXP50-CPP,Yes,Rule,,,Do not depend on the order of evaluation for side effects,,SideEffects1,Hard, +cpp,CERT-C++,EXP51-CPP,Yes,Rule,,,Do not delete an array through a pointer of the incorrect type,,Freed,Hard, +cpp,CERT-C++,EXP52-CPP,Yes,Rule,,,Do not rely on side effects in unevaluated operands,,SideEffects1,Medium, +cpp,CERT-C++,EXP53-CPP,Yes,Rule,,,Do not read uninitialized memory,cpp/not-initialised???,Uninitialized,Very Hard, +cpp,CERT-C++,EXP54-CPP,Yes,Rule,,,Do not access an object outside of its lifetime,,Freed,Very Hard, +cpp,CERT-C++,EXP55-CPP,Yes,Rule,,,Do not access a cv-qualified object through a cv-unqualified type,,Const,Easy, +cpp,CERT-C++,EXP56-CPP,Yes,Rule,,,Do not call a function with a mismatched language linkage,,Functions,Easy, +cpp,CERT-C++,EXP57-CPP,Yes,Rule,,,Do not cast or delete pointers to incomplete classes,,Pointers,Medium, +cpp,CERT-C++,EXP58-CPP,Yes,Rule,,,Pass an object of the correct type to va_start,,Expressions,Medium, +cpp,CERT-C++,EXP59-CPP,Yes,Rule,,,Use offsetof() on valid types and members,,Classes,Medium, +cpp,CERT-C++,EXP60-CPP,Yes,Rule,,,Do not pass a nonstandard-layout type object across execution boundaries,,TrustBoundaries,Hard, +cpp,CERT-C++,EXP61-CPP,Yes,Rule,,,A lambda object must not outlive any of its reference captured objects,EXP54-CPP,Lambdas,Medium, +cpp,CERT-C++,EXP62-CPP,Yes,Rule,,,Do not access the bits of an object representation that are not part of the object's value representation,,Representation,Easy, +cpp,CERT-C++,EXP63-CPP,Yes,Rule,,,Do not rely on the value of a moved-from object,,MoveForward,Hard, +cpp,CERT-C++,FIO50-CPP,Yes,Rule,,,Do not alternately input and output from a file stream without an intervening positioning call,,IO,Medium, +cpp,CERT-C++,FIO51-CPP,Yes,Rule,,,Close files when they are no longer needed,,IO,Medium, +cpp,CERT-C++,INT50-CPP,Yes,Rule,,,Do not cast to an out-of-range enumeration value,A7-2-1,TypeRanges,Hard, +cpp,CERT-C++,MEM50-CPP,Yes,Rule,,,Do not access freed memory,cpp/use-after-free,Freed,Very Hard, +cpp,CERT-C++,MEM51-CPP,Yes,Rule,,,Properly deallocate dynamically allocated resources,cpp/memory-never-freed???,Allocations,Very Hard, +cpp,CERT-C++,MEM52-CPP,Yes,Rule,,,Detect and handle memory allocation errors,,Allocations,Medium, +cpp,CERT-C++,MEM53-CPP,Yes,Rule,,,Explicitly construct and destruct objects when manually managing object lifetime,,Allocations,Medium, +cpp,CERT-C++,MEM54-CPP,Yes,Rule,,,Provide placement new with properly aligned pointers to sufficient storage capacity,,Allocations,Hard, +cpp,CERT-C++,MEM55-CPP,Yes,Rule,,,Honor replacement dynamic storage management requirements,,Allocations,Hard, +cpp,CERT-C++,MEM56-CPP,Yes,Rule,,,Do not store an already-owned pointer value in an unrelated smart pointer,,SmartPointers2,Very Hard, +cpp,CERT-C++,MEM57-CPP,Yes,Rule,,,Avoid using default operator new for over-aligned types,,Allocations,Easy, +cpp,CERT-C++,MSC50-CPP,Yes,Rule,,,Do not use std::rand() for generating pseudorandom numbers,,BannedFunctions,Easy, +cpp,CERT-C++,MSC51-CPP,Yes,Rule,,,Ensure your random number generator is properly seeded,,Initialization,Medium, +cpp,CERT-C++,MSC52-CPP,Yes,Rule,,,Value-returning functions must return a value from all exit paths,cpp/missing-return,Functions,Easy, +cpp,CERT-C++,MSC53-CPP,Yes,Rule,,,Do not return from a function declared [[noreturn]],,Functions,Easy, +cpp,CERT-C++,MSC54-CPP,Yes,Rule,,,A signal handler must be a plain old function,,Invariants,Medium, +cpp,CERT-C++,OOP50-CPP,Yes,Rule,,,Do not invoke virtual functions from constructors or destructors,,Inheritance,Easy, +cpp,CERT-C++,OOP51-CPP,Yes,Rule,,,Do not slice derived objects,,Inheritance,Medium, +cpp,CERT-C++,OOP52-CPP,Yes,Rule,,,Do not delete a polymorphic object without a virtual destructor,A12-4-1,Inheritance,Easy, +cpp,CERT-C++,OOP53-CPP,Yes,Rule,,,Write constructor member initializers in the canonical order,,Initialization,Easy, +cpp,CERT-C++,OOP54-CPP,Yes,Rule,,,Gracefully handle self-copy assignment,"cpp/jsf/av-rule-81?, cpp/self-assignment-check?",OperatorInvariants,Hard, +cpp,CERT-C++,OOP55-CPP,Yes,Rule,,,Do not use pointer-to-member operators to access nonexistent members,,Pointers,Medium, +cpp,CERT-C++,OOP56-CPP,Yes,Rule,,,Honor replacement handler requirements,,Invariants,Easy, +cpp,CERT-C++,OOP57-CPP,Yes,Rule,,,Prefer special member functions and overloaded operators to C Standard Library functions,EXP62-CPP,BannedFunctions,Easy, +cpp,CERT-C++,OOP58-CPP,Yes,Rule,,,Copy operations must not mutate the source object,,OperatorInvariants,Medium, +cpp,CERT-C++,STR50-CPP,Yes,Rule,,,Guarantee that storage for strings has sufficient space for character data and the null terminator,,Strings,Very Hard, +cpp,CERT-C++,STR51-CPP,Yes,Rule,,,Do not attempt to create a std::string from a null pointer,,Null,Hard, +cpp,CERT-C++,STR52-CPP,Yes,Rule,,,"Use valid references, pointers, and iterators to reference elements of a basic_string",,Iterators,Hard, +cpp,CERT-C++,STR53-CPP,Yes,Rule,,,Range check element access,,OutOfBounds,Hard, +c,CERT-C,ARR30-C,Yes,Rule,,,Do not form or use out-of-bounds pointers or array subscripts,,InvalidMemory,Medium, +c,CERT-C,ARR32-C,Yes,Rule,,,Ensure size arguments for variable length arrays are in a valid range,,InvalidMemory,Medium, +c,CERT-C,ARR36-C,Yes,Rule,,,Do not subtract or compare two pointers that do not refer to the same array,,Memory,Medium, +c,CERT-C,ARR37-C,Yes,Rule,,,Do not add or subtract an integer to a pointer to a non-array object,,InvalidMemory,Medium, +c,CERT-C,ARR38-C,Yes,Rule,,,Guarantee that library functions do not form invalid pointers,,Pointers,Medium, +c,CERT-C,ARR39-C,Yes,Rule,,,Do not add or subtract a scaled integer to a pointer,,Pointers,Medium, +c,CERT-C,CON30-C,Yes,Rule,,,Clean up thread-specific storage,,Concurrency,Very Hard, +c,CERT-C,CON31-C,Yes,Rule,,,Do not destroy a mutex while it is locked,CON50-CPP,Concurrency,Very Hard, +c,CERT-C,CON32-C,Yes,Rule,,,Prevent data races when accessing bit-fields from multiple threads,,Concurrency,Easy, +c,CERT-C,CON33-C,Yes,Rule,,,Avoid race conditions when using library functions,,Concurrency,Easy, +c,CERT-C,CON34-C,Yes,Rule,,,Declare objects shared between threads with appropriate storage durations,,Concurrency,Hard, +c,CERT-C,CON35-C,Yes,Rule,,,Avoid deadlock by locking in a predefined order,CON53-CPP,Concurrency,Medium, +c,CERT-C,CON36-C,Yes,Rule,,,Wrap functions that can spuriously wake up in a loop,CON54-CPP,Concurrency,Medium, +c,CERT-C,CON37-C,Yes,Rule,,,Do not call signal() in a multithreaded program,,Concurrency,Easy, +c,CERT-C,CON38-C,Yes,Rule,,,Preserve thread safety and liveness when using condition variables,CON55-CPP,Concurrency,Medium, +c,CERT-C,CON39-C,Yes,Rule,,,Do not join or detach a thread that was previously joined or detached,,Concurrency,Hard, +c,CERT-C,CON40-C,Yes,Rule,,,Do not refer to an atomic variable twice in an expression,,Concurrency,Medium, +c,CERT-C,CON41-C,Yes,Rule,,,Wrap functions that can fail spuriously in a loop,CON53-CPP,Concurrency,Medium, +c,CERT-C,CON43-C,OutOfScope,Rule,,,Do not allow data races in multithreaded code,,,, +c,CERT-C,DCL30-C,Yes,Rule,,,Declare objects with appropriate storage durations,,Declarations,Hard, +c,CERT-C,DCL31-C,Yes,Rule,,,Declare identifiers before using them,,Declarations,Medium, +c,CERT-C,DCL36-C,Yes,Rule,,,Do not declare an identifier with conflicting linkage classifications,,Declarations,Medium, +c,CERT-C,DCL37-C,Yes,Rule,,,Do not declare or define a reserved identifier,,Declarations,Easy, +c,CERT-C,DCL38-C,Yes,Rule,,,Use the correct syntax when declaring a flexible array member,,Declarations,Easy, +c,CERT-C,DCL39-C,Yes,Rule,,,Avoid information leakage when passing a structure across a trust boundary,,Declarations,Hard, +c,CERT-C,DCL40-C,Yes,Rule,,,Do not create incompatible declarations of the same function or object,,Declarations,Hard, +c,CERT-C,DCL41-C,Yes,Rule,,,Do not declare variables inside a switch statement before the first case label,,Declarations,Medium, +c,CERT-C,ENV30-C,Yes,Rule,,,Do not modify the object referenced by the return value of certain functions,RULE-21-19,Contracts,Medium, +c,CERT-C,ENV31-C,Yes,Rule,,,Do not rely on an environment pointer following an operation that may invalidate it,RULE-21-20,Contracts,Hard, +c,CERT-C,ENV32-C,Yes,Rule,,,All exit handlers must return normally,,Contracts,Medium, +c,CERT-C,ENV33-C,Yes,Rule,,,Do not call system(),"RULE-21-21, M18-0-3",Banned,Easy, +c,CERT-C,ENV34-C,Yes,Rule,,,Do not store pointers returned by certain functions,RULE-21-20,Contracts,Medium, +c,CERT-C,ERR30-C,Yes,Rule,,,"Set errno to zero before calling a library function known to set errno, and check errno only after the function returns a value indicating failure",M19-3-1,Contracts,Hard, +c,CERT-C,ERR32-C,Yes,Rule,,,Do not rely on indeterminate values of errno,,Contracts,Hard, +c,CERT-C,ERR33-C,Yes,Rule,,,Detect and handle standard library errors,MEM52-CPP,Contracts,Hard, +c,CERT-C,ERR34-C,OutOfScope,Rule,,,Detect errors when converting a string to a number,,,, +c,CERT-C,EXP30-C,Yes,Rule,,,Do not depend on the order of evaluation for side effects,EXP50-CPP,SideEffects,Easy, +c,CERT-C,EXP32-C,Yes,Rule,,,Do not access a volatile object through a nonvolatile reference,,Pointers,Easy, +c,CERT-C,EXP33-C,Yes,Rule,,,Do not read uninitialized memory,EXP53-CPP,InvalidMemory,Easy, +c,CERT-C,EXP34-C,Yes,Rule,,,Do not dereference null pointers,A5-3-2,InvalidMemory,Medium, +c,CERT-C,EXP35-C,Yes,Rule,,,Do not modify objects with temporary lifetime,,InvalidMemory,Hard, +c,CERT-C,EXP36-C,Yes,Rule,,,Do not cast pointers into more strictly aligned pointer types,,Pointers,Medium, +c,CERT-C,EXP37-C,Yes,Rule,,,Call functions with the correct number and type of arguments,,Expressions,Easy, +c,CERT-C,EXP39-C,Yes,Rule,,,Do not access a variable through a pointer of an incompatible type,,Pointers,Medium, +c,CERT-C,EXP40-C,Yes,Rule,,,Do not modify constant objects,,Contracts,Medium, +c,CERT-C,EXP42-C,Yes,Rule,,,Do not compare padding data,,Memory,Medium, +c,CERT-C,EXP43-C,Yes,Rule,,,Avoid undefined behavior when using restrict-qualified pointers,,Pointers,Medium, +c,CERT-C,EXP44-C,Yes,Rule,,,"Do not rely on side effects in operands to sizeof, _Alignof, or _Generic",M5-3-4,SideEffects,Medium, +c,CERT-C,EXP45-C,Yes,Rule,,,Do not perform assignments in selection statements,M6-2-1,SideEffects,Medium, +c,CERT-C,EXP46-C,Yes,Rule,,,Do not use a bitwise operator with a Boolean-like operand,,Expressions,Easy, +c,CERT-C,EXP47-C,OutOfScope,Rule,,,Do not call va_arg with an argument of the incorrect type,,,, +c,CERT-C,FIO30-C,Yes,Rule,,,Exclude user input from format strings,A27-0-1,IO1,Import, +c,CERT-C,FIO32-C,Yes,Rule,,,Do not perform operations on devices that are only appropriate for files,,IO,Medium, +c,CERT-C,FIO34-C,Yes,Rule,,,Distinguish between characters read from a file and EOF or WEOF,,IO1,Hard, +c,CERT-C,FIO37-C,Yes,Rule,,,Do not assume that fgets() or fgetws() returns a nonempty string when successful,,IO,Medium, +c,CERT-C,FIO38-C,Yes,Rule,,,Do not copy a FILE object,,IO,Medium, +c,CERT-C,FIO39-C,Yes,Rule,,,Do not alternately input and output from a stream without an intervening flush or positioning call,FIO50-CPP A27-0-3,IO1,Medium, +c,CERT-C,FIO40-C,Yes,Rule,,,Reset strings on fgets() or fgetws() failure,,IO,Medium, +c,CERT-C,FIO41-C,Yes,Rule,,,"Do not call getc(), putc(), getwc(), or putwc() with a stream argument that has side effects",,IO,Medium, +c,CERT-C,FIO42-C,Yes,Rule,,,Close files when they are no longer needed,FIO51-CPP,IO1,Medium, +c,CERT-C,FIO44-C,Yes,Rule,,,Only use values for fsetpos() that are returned from fgetpos(),,IO,Medium, +c,CERT-C,FIO45-C,Yes,Rule,,,Avoid TOCTOU race conditions while accessing files,,IO,Medium, +c,CERT-C,FIO46-C,Yes,Rule,,,Do not access a closed file,FIO51-CPP,IO1,Hard, +c,CERT-C,FIO47-C,Yes,Rule,,,Use valid format strings,,IO,Hard, +c,CERT-C,FLP30-C,Yes,Rule,,,Do not use floating-point variables as loop counters,,Statements,Easy, +c,CERT-C,FLP32-C,Yes,Rule,,,Prevent or detect domain and range errors in math functions,A0-4-4,Types,Medium, +c,CERT-C,FLP34-C,Yes,Rule,,,Ensure that floating-point conversions are within range of the new type,,Types,Medium, +c,CERT-C,FLP36-C,Yes,Rule,,,Preserve precision when converting integral values to floating-point type,,Types,Medium, +c,CERT-C,FLP37-C,Yes,Rule,,,Do not use object representations to compare floating-point values,,Types,Medium, +c,CERT-C,INT30-C,Yes,Rule,,,Ensure that unsigned integer operations do not wrap,A4-7-1,Types,Hard, +c,CERT-C,INT31-C,Yes,Rule,,,Ensure that integer conversions do not result in lost or misinterpreted data,A4-7-1,Types,Hard, +c,CERT-C,INT32-C,Yes,Rule,,,Ensure that operations on signed integers do not result in overflow,A4-7-1,Types,Hard, +c,CERT-C,INT33-C,Yes,Rule,,,Ensure that division and remainder operations do not result in divide-by-zero errors,,Types,Hard, +c,CERT-C,INT34-C,Yes,Rule,,,Do not shift an expression by a negative number of bits or by greater than or equal to the number of bits that exist in the operand,M5-8-1,Types,Import, +c,CERT-C,INT35-C,Yes,Rule,,,Use correct integer precisions,,Types,Hard, +c,CERT-C,INT36-C,Yes,Rule,,,Converting a pointer to integer or integer to pointer,M5-2-9,Types,Easy, +c,CERT-C,MEM30-C,Yes,Rule,,,Do not access freed memory,MEM50-CPP,InvalidMemory,Hard, +c,CERT-C,MEM31-C,Yes,Rule,,,Free dynamically allocated memory when no longer needed,,Memory,Very Hard, +c,CERT-C,MEM33-C,Yes,Rule,,,Allocate and copy structures containing a flexible array member dynamically,,Memory,Very Hard, +c,CERT-C,MEM34-C,Yes,Rule,,,Only free memory allocated dynamically,,Memory,Hard, +c,CERT-C,MEM35-C,Yes,Rule,,,Allocate sufficient memory for an object,,Memory,Very Hard, +c,CERT-C,MEM36-C,Yes,Rule,,,Do not modify the alignment of objects by calling realloc(),,Memory,Medium, +c,CERT-C,MSC30-C,Yes,Rule,,,Do not use the rand() function for generating pseudorandom numbers,MSC50-CPP,Misc,Easy, +c,CERT-C,MSC32-C,Yes,Rule,,,Properly seed pseudorandom number generators,MSC51-CPP,Misc,Easy, +c,CERT-C,MSC33-C,Yes,Rule,,,Do not pass invalid data to the asctime() function,,Contracts,Easy, +c,CERT-C,MSC37-C,Yes,Rule,,,Ensure that control never reaches the end of a non-void function,,Misc,Easy, +c,CERT-C,MSC38-C,Yes,Rule,,,Do not treat a predefined identifier as an object if it might only be implemented as a macro,M17-0-2,Preprocessor,Medium, +c,CERT-C,MSC39-C,Yes,Rule,,,Do not call va_arg() on a va_list that has an indeterminate value,,Contracts,Hard, +c,CERT-C,MSC40-C,Yes,Rule,,,Do not violate constraints,,Contracts,Very Hard, +c,CERT-C,MSC41-C,OutOfScope,Rule,,,Never hard code sensitive information,,,, +c,CERT-C,POS30-C,OutOfScope,Rule,,,Use the readlink() function properly,,,, +c,CERT-C,POS34-C,OutOfScope,Rule,,,Do not call putenv() with a pointer to an automatic variable as the argument,,,, +c,CERT-C,POS35-C,OutOfScope,Rule,,,Avoid race conditions while checking for the existence of a symbolic link,,,, +c,CERT-C,POS36-C,OutOfScope,Rule,,,Observe correct revocation order while relinquishing privileges,,,, +c,CERT-C,POS37-C,OutOfScope,Rule,,,Ensure that privilege relinquishment is successful,,,, +c,CERT-C,POS38-C,OutOfScope,Rule,,,Beware of race conditions when using fork and file descriptors,,,, +c,CERT-C,POS39-C,OutOfScope,Rule,,,Use the correct byte ordering when transferring data between systems,,,, +c,CERT-C,POS44-C,OutOfScope,Rule,,,Do not use signals to terminate threads,,,, +c,CERT-C,POS47-C,OutOfScope,Rule,,,Do not use threads that can be canceled asynchronously,,,, +c,CERT-C,POS48-C,OutOfScope,Rule,,,Do not unlock or destroy another POSIX thread's mutex,,,, +c,CERT-C,POS49-C,OutOfScope,Rule,,,"When data must be accessed by multiple threads, provide a mutex and guarantee no adjacent data is also accessed",,,, +c,CERT-C,POS50-C,OutOfScope,Rule,,,Declare objects shared between POSIX threads with appropriate storage durations,,,, +c,CERT-C,POS51-C,OutOfScope,Rule,,,Avoid deadlock with POSIX threads by locking in predefined order,,,, +c,CERT-C,POS52-C,OutOfScope,Rule,,,Do not perform operations that can block while holding a POSIX lock,,,, +c,CERT-C,POS53-C,OutOfScope,Rule,,,Do not use more than one mutex for concurrent waiting operations on a condition variable,,,, +c,CERT-C,POS54-C,OutOfScope,Rule,,,Detect and handle POSIX library errors,,,, +c,CERT-C,PRE30-C,Yes,Rule,,,Do not create a universal character name through concatenation,,Preprocessor,Medium, +c,CERT-C,PRE31-C,Yes,Rule,,,Avoid side effects in arguments to unsafe macros,RULE-13-2,SideEffects,Medium, +c,CERT-C,PRE32-C,Yes,Rule,,,Do not use preprocessor directives in invocations of function-like macros,,Preprocessor,Hard, +c,CERT-C,SIG30-C,Yes,Rule,,,Call only asynchronous-safe functions within signal handlers,,Contracts,Medium, +c,CERT-C,SIG31-C,Yes,Rule,,,Do not access shared objects in signal handlers,,Contracts,Medium, +c,CERT-C,SIG34-C,Yes,Rule,,,Do not call signal() from within interruptible signal handlers,,Contracts,Medium, +c,CERT-C,SIG35-C,Yes,Rule,,,Do not return from a computational exception signal handler,,Contracts,Easy, +c,CERT-C,STR30-C,Yes,Rule,,,Do not attempt to modify string literals,,Strings,Medium, +c,CERT-C,STR31-C,Yes,Rule,,,Guarantee that storage for strings has sufficient space for character data and the null terminator,STR50-CPP,Strings,Very Hard, +c,CERT-C,STR32-C,Yes,Rule,,,Do not pass a non-null-terminated character sequence to a library function that expects a string,STR51-CPP,Strings,Very Hard, +c,CERT-C,STR34-C,Yes,Rule,,,Cast characters to unsigned char before converting to larger integer sizes,,Strings,Hard, +c,CERT-C,STR37-C,Yes,Rule,,,Arguments to character-handling functions must be representable as an unsigned char,,Strings,Medium, +c,CERT-C,STR38-C,Yes,Rule,,,Do not confuse narrow and wide character strings and functions,,Strings,Medium, +c,CERT-C,WIN30-C,OutOfScope,Rule,,,Properly pair allocation and deallocation functions,DCL54-CPP,,Easy, +c,MISRA-C-2012,RULE-1-1,No,Required,,,Any implementation-defined behaviour on which the output of the program depends shall be documented and understood,,,, +c,MISRA-C-2012,RULE-2-1,Yes,Required,,,All source files shall compile without any compilation errors,A1-4-3,Language,Medium, +c,MISRA-C-2012,RULE-3-1,No,Required,,,All code shall be traceable to documented requirements,,,, +c,MISRA-C-2012,RULE-4-1,No,Required,,,Run-time failures shall be minimized,,,, +c,MISRA-C-2012,RULE-4-2,Yes,Advisory,,,All usage of assembly language should be documented,M7-4-1,Language,Import, +c,MISRA-C-2012,RULE-4-3,Yes,Required,,,Assembly language shall be encapsulated and isolated,,Language,Medium, +c,MISRA-C-2012,RULE-4-4,Yes,Advisory,,,Sections of code should not be commented out,A2-7-2,Syntax,Import, +c,MISRA-C-2012,RULE-4-5,Yes,Advisory,,,Identifiers in the same name space with overlapping visibility should be typographically unambiguous,M2-10-1,Syntax,Easy, +c,MISRA-C-2012,RULE-4-6,Yes,Advisory,,,typedefs that indicate size and signedness should be used in place of the basic numerical types,,Types,Hard, +c,MISRA-C-2012,RULE-4-7,Yes,Required,,,"If a function returns error information, then that error information shall be tested",M0-3-2,Contracts,Import, +c,MISRA-C-2012,RULE-4-8,Yes,Advisory,,,"If a pointer to a structure or union is never dereferenced within a translation unit, then the implementation of the object should be hidden",,Pointers,Medium, +c,MISRA-C-2012,RULE-4-9,Yes,Advisory,,,A function should be used in preference to a function-like macro where they are interchangeable,,Preprocessor,Medium, +c,MISRA-C-2012,RULE-4-10,Yes,Required,,,Precautions shall be taken in order to prevent the contents of a header file being included more than once,,Preprocessor,Medium, +c,MISRA-C-2012,RULE-4-11,Yes,Required,,,The validity of values passed to library functions shall be checked,,Contracts,Hard, +c,MISRA-C-2012,RULE-4-12,Yes,Required,,,Dynamic memory allocation shall not be used,,Banned,Medium, +c,MISRA-C-2012,RULE-4-13,Yes,Advisory,,,Functions which are designed to provide operations on a resource should be called in an appropriate sequence,,Contracts,Hard, +c,MISRA-C-2012,RULE-4-14,Yes,Required,,,The validity of values received from external sources shall be checked,,Contracts,Hard, +c,MISRA-C-2012,RULE-1-1,Yes,Required,,,"The program shall contain no violations of the standard C syntax and constraints, and shall not exceed the implementation๏ฟฝs translation limits",,Language,Easy, +c,MISRA-C-2012,RULE-1-2,Yes,Advisory,,,Language extensions should not be used,,Language,Easy, +c,MISRA-C-2012,RULE-1-3,Yes,Required,,,There shall be no occurrence of undefined or critical unspecified behaviour,,Language,Hard, +c,MISRA-C-2012,RULE-1-4,Yes,Required,,,Emergent language features shall not be used,,Language,Medium, +c,MISRA-C-2012,RULE-2-1,Yes,Required,,,A project shall not contain unreachable code,M0-1-1,DeadCode,Import, +c,MISRA-C-2012,RULE-2-2,Yes,Required,,,There shall be no dead code,M0-1-9,DeadCode,Import, +c,MISRA-C-2012,RULE-2-3,Yes,Advisory,,,A project should not contain unused type declarations,A0-1-6,DeadCode,Import, +c,MISRA-C-2012,RULE-2-4,Yes,Advisory,,,A project should not contain unused tag declarations,,DeadCode,Easy, +c,MISRA-C-2012,RULE-2-5,Yes,Advisory,,,A project should not contain unused macro declarations,,DeadCode,Easy, +c,MISRA-C-2012,RULE-2-6,Yes,Advisory,,,A function should not contain unused label declarations,,DeadCode,Easy, +c,MISRA-C-2012,RULE-2-7,Yes,Advisory,,,There should be no unused parameters in functions,A0-1-4 A0-1-5,DeadCode,Easy, +c,MISRA-C-2012,RULE-3-1,Yes,Required,,,The character sequences /* and // shall not be used within a comment,M2-7-1,Syntax,Easy, +c,MISRA-C-2012,RULE-3-2,Yes,Required,,,Line-splicing shall not be used in // comments,,Syntax,Easy, +c,MISRA-C-2012,RULE-4-1,Yes,Required,,,Octal and hexadecimal escape sequences shall be terminated,A2-13-1 M2-13-2,Syntax,Medium, +c,MISRA-C-2012,RULE-4-2,Yes,Advisory,,,Trigraphs should not be used,A2-5-1,Banned,Import, +c,MISRA-C-2012,RULE-5-1,Yes,Required,,,External identifiers shall be distinct,,Declarations,Medium, +c,MISRA-C-2012,RULE-5-2,Yes,Required,,,Identifiers declared in the same scope and name space shall be distinct,,Declarations,Medium, +c,MISRA-C-2012,RULE-5-3,Yes,Required,,,An identifier declared in an inner scope shall not hide an identifier declared in an outer scope,A2-10-1,Declarations,Import, +c,MISRA-C-2012,RULE-5-4,Yes,Required,,,Macro identifiers shall be distinct,,Declarations,Easy, +c,MISRA-C-2012,RULE-5-5,Yes,Required,,,Identifiers shall be distinct from macro names,,Declarations,Easy, +c,MISRA-C-2012,RULE-5-6,Yes,Required,,,A typedef name shall be a unique identifier,,Declarations,Easy, +c,MISRA-C-2012,RULE-5-7,Yes,Required,,,A tag name shall be a unique identifier,,Declarations,Easy, +c,MISRA-C-2012,RULE-5-8,Yes,Required,,,Identifiers that define objects or functions with external linkage shall be unique,,Declarations,Easy, +c,MISRA-C-2012,RULE-5-9,Yes,Advisory,,,Identifiers that define objects or functions with internal linkage should be unique,,Declarations,Easy, +c,MISRA-C-2012,RULE-6-1,Yes,Required,,,Bit-fields shall only be declared with an appropriate type,M9-6-4,Types,Medium, +c,MISRA-C-2012,RULE-6-2,Yes,Required,,,Single-bit named bit fields shall not be of a signed type,M9-6-4,Types,Import, +c,MISRA-C-2012,RULE-7-1,Yes,Required,,,Octal constants shall not be used,M2-13-2,Banned,Import, +c,MISRA-C-2012,RULE-7-2,Yes,Required,,,A ๏ฟฝu๏ฟฝ or ๏ฟฝU๏ฟฝ suffix shall be applied to all integer constants that are represented in an unsigned type,M2-13-3,Syntax,Easy, +c,MISRA-C-2012,RULE-7-3,Yes,Required,,,The lowercase character ๏ฟฝl๏ฟฝ shall not be used in a literal suffix,M2-13-4,Syntax,Easy, +c,MISRA-C-2012,RULE-7-4,Yes,Required,,,A string literal shall not be assigned to an object unless the object๏ฟฝs type is ๏ฟฝpointer to const-qualified char๏ฟฝ,A2-13-4,Types,Easy, +c,MISRA-C-2012,RULE-8-1,Yes,Required,,,Types shall be explicitly specified,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-2,Yes,Required,,,Function types shall be in prototype form with named parameters,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-3,Yes,Required,,,All declarations of an object or function shall use the same names and type qualifiers,M3-2-1,Declarations,Medium, +c,MISRA-C-2012,RULE-8-4,Yes,Required,,,A compatible declaration shall be visible when an object or function with external linkage is defined,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-5,Yes,Required,,,An external object or function shall be declared once in one and only one file,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-6,Yes,Required,,,An identifier with external linkage shall have exactly one external definition,M3-2-4,Declarations,Import, +c,MISRA-C-2012,RULE-8-7,Yes,Advisory,,,Functions and objects should not be defined with external linkage if they are referenced in only one translation unit,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-8,Yes,Required,,,The static storage class specifier shall be used in all declarations of objects and functions that have internal linkage,M3-3-2,Declarations,Medium, +c,MISRA-C-2012,RULE-8-9,Yes,Advisory,,,An object should be defined at block scope if its identifier only appears in a single function,M3-4-1,Declarations,Medium, +c,MISRA-C-2012,RULE-8-10,Yes,Required,,,An inline function shall be declared with the static storage class,,Declarations,Medium, +c,MISRA-C-2012,RULE-8-11,Yes,Advisory,,,"When an array with external linkage is declared, its size should be explicitly specified",,Declarations,Medium, +c,MISRA-C-2012,RULE-8-12,Yes,Required,,,"Within an enumerator list, the value of an implicitly-specified enumeration constant shall be unique",,Declarations,Medium, +c,MISRA-C-2012,RULE-8-13,Yes,Advisory,,,A pointer should point to a const-qualified type whenever possible,,Pointers,Medium, +c,MISRA-C-2012,RULE-8-14,Yes,Required,,,The restrict type qualifier shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-9-1,Yes,Mandatory,,,The value of an object with automatic storage duration shall not be read before it has been set,,InvalidMemory,Medium, +c,MISRA-C-2012,RULE-9-2,Yes,Required,,,The initializer for an aggregate or union shall be enclosed in braces,,Memory,Easy, +c,MISRA-C-2012,RULE-9-3,Yes,Required,,,Arrays shall not be partially initialized,,Memory,Medium, +c,MISRA-C-2012,RULE-9-4,Yes,Required,,,An element of an object shall not be initialized more than once,,Memory,Medium, +c,MISRA-C-2012,RULE-9-5,Yes,Required,,,Where designated initializers are used to initialize an array object the size of the array shall be specified explicitly,,Memory,Medium, +c,MISRA-C-2012,RULE-10-1,Yes,Required,,,Operands shall not be of an inappropriate essential type,,Types,Hard, +c,MISRA-C-2012,RULE-10-2,Yes,Required,,,Expressions of essentially character type shall not be used inappropriately in addition and subtraction operations,,Types,Medium, +c,MISRA-C-2012,RULE-10-3,Yes,Required,,,The value of an expression shall not be assigned to an object with a narrower essential type or of a different essential type category,,Types,Hard, +c,MISRA-C-2012,RULE-10-4,Yes,Required,,,Both operands of an operator in which the usual arithmetic conversions are performed shall have the same essential type category,,Types,Medium, +c,MISRA-C-2012,RULE-10-5,Yes,Advisory,,,The value of an expression should not be cast to an inappropriate essential type,,Types,Medium, +c,MISRA-C-2012,RULE-10-6,Yes,Required,,,The value of a composite expression shall not be assigned to an object with wider essential type,,Types,Medium, +c,MISRA-C-2012,RULE-10-7,Yes,Required,,,If a composite expression is used as one operand of an operator in which the usual arithmetic conversions are performed then the other operand shall not have wider essential type,,Types,Medium, +c,MISRA-C-2012,RULE-10-8,Yes,Required,,,The value of a composite expression shall not be cast to a different essential type category or a wider essential type,,Types,Medium, +c,MISRA-C-2012,RULE-11-1,Yes,Required,,,Conversions shall not be performed between a pointer to a function and any other type,M5-2-6,Pointers,Import, +c,MISRA-C-2012,RULE-11-2,Yes,Required,,,Conversions shall not be performed between a pointer to an incomplete type and any other type,,Pointers,Easy, +c,MISRA-C-2012,RULE-11-3,Yes,Required,,,A cast shall not be performed between a pointer to object type and a pointer to a different object type,,Pointers,Easy, +c,MISRA-C-2012,RULE-11-4,Yes,Advisory,,,A conversion should not be performed between a pointer to object and an integer type,M-2-9,Pointers,Import, +c,MISRA-C-2012,RULE-11-5,Yes,Advisory,,,A conversion should not be performed from pointer to void into pointer to object,,Pointers,Easy, +c,MISRA-C-2012,RULE-11-6,Yes,Required,,,A cast shall not be performed between pointer to void and an arithmetic type,,Pointers,Easy, +c,MISRA-C-2012,RULE-11-7,Yes,Required,,,A cast shall not be performed between pointer to object and a non- integer arithmetic type,,Pointers,Easy, +c,MISRA-C-2012,RULE-11-8,Yes,Required,,,A cast shall not remove any const or volatile qualification from the type pointed to by a pointer,,Pointers,Easy, +c,MISRA-C-2012,RULE-11-9,Yes,Required,,,The macro NULL shall be the only permitted form of integer null pointer constant,,Pointers,Easy, +c,MISRA-C-2012,RULE-12-1,Yes,Advisory,,,The precedence of operators within expressions should be made explicit,,SideEffects,Medium, +c,MISRA-C-2012,RULE-12-2,Yes,Required,,,The right hand operand of a shift operator shall lie in the range zero to one less than the width in bits of the essential type of the left hand operand,,Contracts,Hard, +c,MISRA-C-2012,RULE-12-3,Yes,Advisory,,,The comma operator should not be used,M5-18-1,Banned,Import, +c,MISRA-C-2012,RULE-12-4,Yes,Advisory,,,Evaluation of constant expressions should not lead to unsigned integer wrap-around,INT30-C,Types,Easy, +c,MISRA-C-2012,RULE-12-5,Yes,Mandatory,,,The sizeof operator shall not have an operand which is a function parameter declared as ๏ฟฝarray of type๏ฟฝ,,Types,Medium, +c,MISRA-C-2012,RULE-13-1,Yes,Required,,,Initializer lists shall not contain persistent side effects,,SideEffects,Medium, +c,MISRA-C-2012,RULE-13-2,Yes,Required,,,The value of an expression and its persistent side effects shall be the same under all permitted evaluation orders,PRE31-C,SideEffects,Medium, +c,MISRA-C-2012,RULE-13-3,Yes,Advisory,,,A full expression containing an increment (++) or decrement (--) operator should have no other potential side effects other than that caused by the increment or decrement operator,,SideEffects,Medium, +c,MISRA-C-2012,RULE-13-4,Yes,Advisory,,,The result of an assignment operator should not be used,M6-2-1,SideEffects,Easy, +c,MISRA-C-2012,RULE-13-5,Yes,Required,,,The right hand operand of a logical && or || operator shall not contain persistent side effects,M5-14-1,SideEffects,Import, +c,MISRA-C-2012,RULE-13-6,Yes,Mandatory,,,The operand of the sizeof operator shall not contain any expression which has potential side effects,M5-3-4,SideEffects,Import, +c,MISRA-C-2012,RULE-14-1,Yes,Required,,,A loop counter shall not have essentially floating type,FLP30-C A6-5-2,Types,Hard, +c,MISRA-C-2012,RULE-14-2,Yes,Required,,,A for loop shall be well-formed,M6-5-1...M6-5-6,Statements,Medium, +c,MISRA-C-2012,RULE-14-3,Yes,Required,,,Controlling expressions shall not be invariant,,Statements,Medium, +c,MISRA-C-2012,RULE-14-4,Yes,Required,,,The controlling expression of an if statement and the controlling expression of an iteration-statement shall have essentially Boolean type,A5-0-2,Statements,Medium, +c,MISRA-C-2012,RULE-15-1,Yes,Advisory,,,The goto statement should not be used,A6-6-1,Banned,Import, +c,MISRA-C-2012,RULE-15-2,Yes,Required,,,The goto statement shall jump to a label declared later in the same function,M6-6-2,Statements,Import, +c,MISRA-C-2012,RULE-15-3,Yes,Required,,,"Any label referenced by a goto statement shall be declared in the same block, or in any block enclosing the goto statement",M6-6-1,Statements,Import, +c,MISRA-C-2012,RULE-15-4,Yes,Advisory,,,There should be no more than one break or goto statement used to terminate any iteration statement,,Statements,Medium, +c,MISRA-C-2012,RULE-15-5,Yes,Advisory,,,A function should have a single point of exit at the end,,Statements,Medium, +c,MISRA-C-2012,RULE-15-6,Yes,Required,,,The body of an iteration-statement or a selection-statement shall be a compund-statement,M6-3-1,Statements,Import, +c,MISRA-C-2012,RULE-15-7,Yes,Required,,,All if / else if constructs shall be terminated with an else statement,M6-4-2,Statements,Import, +c,MISRA-C-2012,RULE-16-1,Yes,Required,,,All switch statements shall be well-formed,M6-4-3,Statements,Import, +c,MISRA-C-2012,RULE-16-2,Yes,Required,,,A switch label shall only be used when the most closely-enclosing compound statement is the body of a switch statement,M6-4-4,Statements,Import, +c,MISRA-C-2012,RULE-16-3,Yes,Required,,,An unconditional break statement shall terminate every switch-clause,M6-4-5,Statements,Import, +c,MISRA-C-2012,RULE-16-4,Yes,Required,,,Every switch statement shall have a default label,M6-4-6,Statements,Easy, +c,MISRA-C-2012,RULE-16-5,Yes,Required,,,A default label shall appear as either the first or the last switch label of a switch statement,M6-4-6,Statements,Easy, +c,MISRA-C-2012,RULE-16-6,Yes,Required,,,Every switch statement shall have at least two switch-clauses,A6-4-1,Statements,Medium, +c,MISRA-C-2012,RULE-16-7,Yes,Required,,,A switch-expression shall not have essentially Boolean type,M6-4-7,Statements,Medium, +c,MISRA-C-2012,RULE-17-1,Yes,Required,,,The features of shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-17-2,Yes,Required,,,"Functions shall not call themselves, either directly or indirectly",A7-5-2,Statements,Import, +c,MISRA-C-2012,RULE-17-3,Yes,Mandatory,,,A function shall not be declared implicitly,,Declarations,Medium, +c,MISRA-C-2012,RULE-17-4,Yes,Mandatory,,,All exit paths from a function with non-void return type shall have an explicit return statement with an expression,MSC52-CPP,Statements,Medium, +c,MISRA-C-2012,RULE-17-5,Yes,Advisory,,,The function argument corresponding to a parameter declared to have an array type shall have an appropriate number of elements,,Contracts,Hard, +c,MISRA-C-2012,RULE-17-6,Yes,Mandatory,,,The declaration of an array parameter shall not contain the static keyword between the [ ],,Declarations,Easy, +c,MISRA-C-2012,RULE-17-7,Yes,Required,,,The value returned by a function having non-void return type shall be used,A0-1-2,Contracts,Import, +c,MISRA-C-2012,RULE-17-8,Yes,Advisory,,,A function parameter should not be modified,,SideEffects,Medium, +c,MISRA-C-2012,RULE-18-1,Yes,Required,,,A pointer resulting from arithmetic on a pointer operand shall address an element of the same array as that pointer operand,M5-0-16,Pointers,Import, +c,MISRA-C-2012,RULE-18-2,Yes,Required,,,Subtraction between pointers shall only be applied to pointers that address elements of the same array,M5-0-17,Pointers,Import, +c,MISRA-C-2012,RULE-18-3,Yes,Required,,,"The relational operators >, >=, < and <= shall not be applied to objects of pointer type except where they point into the same object",M5-0-18,Pointers,Import, +c,MISRA-C-2012,RULE-18-4,Yes,Advisory,,,"The +, -, += and -= operators should not be applied to an expression of pointer type",,Pointers,Medium, +c,MISRA-C-2012,RULE-18-5,Yes,Advisory,,,Declarations should contain no more than two levels of pointer nesting,,Pointers,Medium, +c,MISRA-C-2012,RULE-18-6,Yes,Required,,,The address of an object with automatic storage shall not be copied to another object that persists after the first object has ceased to exist,M7-5-2,Pointers,Import, +c,MISRA-C-2012,RULE-18-7,Yes,Required,,,Flexible array members shall not be declared,,Declarations,Medium, +c,MISRA-C-2012,RULE-18-8,Yes,Required,,,Variable-length array types shall not be used,,Declarations,Medium, +c,MISRA-C-2012,RULE-19-1,Yes,Mandatory,,,An object shall not be assigned or copied to an overlapping object,M0-2-1,Contracts,Hard, +c,MISRA-C-2012,RULE-19-2,Yes,Advisory,,,The union keyword should not be used,A9-5-1,Banned,Import, +c,MISRA-C-2012,RULE-20-1,Yes,Advisory,,,#include directives should only be preceded by preprocessor directives or comments,M16-0-1,Preprocessor1,Import, +c,MISRA-C-2012,RULE-20-2,Yes,Required,,,"The ', "" or \ characters and the /* or // character sequences shall not occur in a header file name",A16-2-1,Preprocessor1,Import, +c,MISRA-C-2012,RULE-20-3,Yes,Required,,,"The #include directive shall be followed by either a or ""filename"" sequence",,Preprocessor,Easy, +c,MISRA-C-2012,RULE-20-4,Yes,Required,,,A macro shall not be defined with the same name as a keyword,A17-0-1,Preprocessor,Medium, +c,MISRA-C-2012,RULE-20-5,Yes,Advisory,,,#undef should not be used,,Preprocessor,Easy, +c,MISRA-C-2012,RULE-20-6,Yes,Required,,,Tokens that look like a preprocessing directive shall not occur within a macro argument,M16-0-5,Preprocessor,Import, +c,MISRA-C-2012,RULE-20-7,Yes,Required,,,Expressions resulting from the expansion of macro parameters shall be enclosed in parentheses,M16-0-6,Preprocessor,Easy, +c,MISRA-C-2012,RULE-20-8,Yes,Required,,,The controlling expression of a #if or #elif preprocessing directive shall evaluate to 0 or 1,,Preprocessor,Hard, +c,MISRA-C-2012,RULE-20-9,Yes,Required,,,All identifiers used in the controlling expression of #if or #elif preprocessing directives shall be #defined before evaluation,M16-0-7,Preprocessor1,Import, +c,MISRA-C-2012,RULE-20-10,Yes,Advisory,,,The # and ## preprocessor operators should not be used,M16-3-2,Preprocessor1,Import, +c,MISRA-C-2012,RULE-20-11,Yes,Required,,,A macro parameter immediately following a # operator shall not immediately be followed by a ## operator,M16-3-1,Preprocessor,Easy, +c,MISRA-C-2012,RULE-20-12,Yes,Required,,,"A macro parameter used as an operand to the # or ## operators, which is itself subject to further macro replacement, shall only be used as an operand to these operators",,Preprocessor,Medium, +c,MISRA-C-2012,RULE-20-13,Yes,Required,,,A line whose first token is # shall be a valid preprocessing directive,M16-0-8,Preprocessor,Easy, +c,MISRA-C-2012,RULE-20-14,Yes,Required,,,"All #else, #elif and #endif preprocessor directives shall reside in the same file as the #if, #ifdef or #ifndef directive to which they are related",M16-1-2,Preprocessor,Import, +c,MISRA-C-2012,RULE-21-1,Yes,Required,,,#define and #undef shall not be used on a reserved identifier or reserved macro name,,Preprocessor,Hard, +c,MISRA-C-2012,RULE-21-2,Yes,Required,,,A reserved identifier or reserved macro name shall not be declared,,Declarations,Hard, +c,MISRA-C-2012,RULE-21-3,Yes,Required,,,The memory allocation and deallocation functions of shall not be used,,Banned,Medium, +c,MISRA-C-2012,RULE-21-4,Yes,Required,,,The standard header file shall not be used ,,Banned,Easy, +c,MISRA-C-2012,RULE-21-5,Yes,Required,,,The standard header file shall not be used ,,Banned,Easy, +c,MISRA-C-2012,RULE-21-6,Yes,Required,,,The Standard Library input/output functions shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-21-7,Yes,Required,,,"The Standard Library functions atof, atoi, atol and atoll of shall not be used",,Banned,Easy, +c,MISRA-C-2012,RULE-21-8,Yes,Required,,,The Standard Library termination functions of shall not be used,ERR50-CPP,Banned,Easy, +c,MISRA-C-2012,RULE-21-9,Yes,Required,,,The Standard Library functions bsearch and qsort of shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-21-10,Yes,Required,,,The Standard Library time and date functions shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-21-11,Yes,Required,,,The standard header file shall not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-21-12,Yes,Advisory,,,The exception handling features of should not be used,,Banned,Easy, +c,MISRA-C-2012,RULE-21-13,Yes,Mandatory,,,Any value passed to a function in shall be representable as an unsigned char or be the value EOF,,Types,Medium, +c,MISRA-C-2012,RULE-21-14,Yes,Required,,,The Standard Library function memcmp shall not be used to compare null terminated strings,,Types,Hard, +c,MISRA-C-2012,RULE-21-15,Yes,Required,,,"The pointer arguments to the Standard Library functions memcpy, memmove and memcmp shall be pointers to qualified or unqualified versions of compatible types",,Types,Medium, +c,MISRA-C-2012,RULE-21-16,Yes,Required,,,"The pointer arguments to the Standard Library function memcmp shall point to either a pointer type, an essentially signed type, an essentially unsigned type, an essentially Boolean type or an essentially enum type",,Types,Medium, +c,MISRA-C-2012,RULE-21-17,Yes,Mandatory,,,Use of the string handling functions from shall not result in accesses beyond the bounds of the objects referenced by their pointer parameters,,Memory,Hard, +c,MISRA-C-2012,RULE-21-18,Yes,Mandatory,,,The size_t argument passed to any function in shall have an appropriate value,,Expressions,Medium, +c,MISRA-C-2012,RULE-21-19,Yes,Mandatory,,,"The pointers returned by the Standard Library functions localeconv, getenv, setlocale or, strerror shall only be used as if they have pointer to const-qualified type",ENV30-C,Contracts,Easy, +c,MISRA-C-2012,RULE-21-20,Yes,Mandatory,,,"The pointer returned by the Standard Library functions asctime, ctime, gmtime, localtime, localeconv, getenv, setlocale or strerror shall not be used following a subsequent call to the same function","ENV31-C, ENV34-C",Contracts,Easy, +c,MISRA-C-2012,RULE-21-21,Yes,Required,,,The Standard Library function system of shall not be used,ENV33-C,Banned,Import, +c,MISRA-C-2012,RULE-22-1,Yes,Required,,,All resources obtained dynamically by means of Standard Library functions shall be explicitly released,,Memory,Hard, +c,MISRA-C-2012,RULE-22-2,Yes,Mandatory,,,A block of memory shall only be freed if it was allocated by means of a Standard Library function,,Memory,Hard, +c,MISRA-C-2012,RULE-22-3,Yes,Required,,,The same file shall not be open for read and write access at the same time on different streams,,IO,Hard, +c,MISRA-C-2012,RULE-22-4,Yes,Mandatory,,,There shall be no attempt to write to a stream which has been opened as read-only,,IO,Medium, +c,MISRA-C-2012,RULE-22-5,Yes,Mandatory,,,A pointer to a FILE object shall not be dereferenced,,IO,Medium, +c,MISRA-C-2012,RULE-22-6,Yes,Mandatory,,,The value of a pointer to a FILE shall not be used after the associated stream has been closed,FIO46-C,IO1,Import, +c,MISRA-C-2012,RULE-22-7,Yes,Required,,,The macro EOF shall only be compared with the unmodified return value from any Standard Library function capable of returning EOF,,IO,Hard, +c,MISRA-C-2012,RULE-22-8,Yes,Required,,,The value of errno shall be set to zero prior to a call to an errno- setting-function,ERR30-C,Contracts,Import, +c,MISRA-C-2012,RULE-22-9,Yes,Required,,,The value of errno shall be tested against zero after calling an errno-setting-function,,Contracts,Medium, +c,MISRA-C-2012,RULE-22-10,Yes,Required,,,The value of errno shall only be tested when the last function to be called was an errno-setting-function,,Contracts,Medium, diff --git a/scripts/PSCodingStandards/CodingStandards.psd1 b/scripts/PSCodingStandards/CodingStandards.psd1 new file mode 100644 index 0000000000..e1a79bb1cf --- /dev/null +++ b/scripts/PSCodingStandards/CodingStandards.psd1 @@ -0,0 +1,132 @@ +# +# Module manifest for module 'CodingStandards' +# +# Generated by: John L. Singleton +# +# Generated on: 2/16/2022 +# + +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'CodingStandards.psm1' + +# Version number of this module. +ModuleVersion = '1.0' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = '7b04b6f0-410b-43fa-9de4-59be3ac85d8a' + +# Author of this module +Author = 'John L. Singleton' + +# Company or vendor of this module +CompanyName = 'Unknown' + +# Copyright statement for this module +Copyright = '(c) John L. Singleton. All rights reserved.' + +# Description of the functionality provided by this module +# Description = '' + +# Minimum version of the PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# ClrVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @() + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = '*' + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +CmdletsToExport = '*' + +# Variables to export from this module +VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +AliasesToExport = @() + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/scripts/PSCodingStandards/CodingStandards.psm1 b/scripts/PSCodingStandards/CodingStandards.psm1 new file mode 100644 index 0000000000..65d3fe38f6 --- /dev/null +++ b/scripts/PSCodingStandards/CodingStandards.psm1 @@ -0,0 +1,11 @@ +$Functions = @( Get-ChildItem -Path $PSScriptRoot\*.ps1 -ErrorAction SilentlyContinue ) + +foreach($i in $Functions){ + . $i.FullName + + Write-Host "Importing $($i.FullName)" +} + +Export-ModuleMember -Function $Functions.BaseName + +Write-Host "IMPORTING " \ No newline at end of file diff --git a/scripts/PSCodingStandards/Get-Packages.ps1 b/scripts/PSCodingStandards/Get-Packages.ps1 new file mode 100644 index 0000000000..980766b78d --- /dev/null +++ b/scripts/PSCodingStandards/Get-Packages.ps1 @@ -0,0 +1,8 @@ +function Get-Packages { + param([Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language) + + return Get-ChildItem (Join-Path (Get-RepositoryRoot) "\rule_packages\$Language\*.json") +} \ No newline at end of file diff --git a/scripts/matrix_testing/GetRepositoryRoot.ps1 b/scripts/PSCodingStandards/Get-RepositoryRoot.ps1 similarity index 100% rename from scripts/matrix_testing/GetRepositoryRoot.ps1 rename to scripts/PSCodingStandards/Get-RepositoryRoot.ps1 diff --git a/scripts/matrix_testing/GetRulesInPackageAndSuite.ps1 b/scripts/PSCodingStandards/Get-RulesInPackageAndSuite.ps1 similarity index 96% rename from scripts/matrix_testing/GetRulesInPackageAndSuite.ps1 rename to scripts/PSCodingStandards/Get-RulesInPackageAndSuite.ps1 index 561122b0da..95c041924e 100644 --- a/scripts/matrix_testing/GetRulesInPackageAndSuite.ps1 +++ b/scripts/PSCodingStandards/Get-RulesInPackageAndSuite.ps1 @@ -1,5 +1,5 @@ -function Get-Rules-In-Package-And-Suite { +function Get-RulesInPackageAndSuite { param( [Parameter(Mandatory)] [System.IO.FileSystemInfo] diff --git a/scripts/PSCodingStandards/Get-RulesInSuite.ps1 b/scripts/PSCodingStandards/Get-RulesInSuite.ps1 new file mode 100644 index 0000000000..f0683e34a1 --- /dev/null +++ b/scripts/PSCodingStandards/Get-RulesInSuite.ps1 @@ -0,0 +1,20 @@ +function Get-RulesInSuite { + param( + [Parameter(Mandatory)] + [string] + $Suite, + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language + ) + + $tmpQueries = @() + + foreach ($p in Get-Packages -Language $Language) { + Write-Host "Reading package: [$Language/$Suite/$($p.BaseName)]" + $tmpQueries += Get-RulesInPackageAndSuite -Package $p -Suite $Suite + } + + return $tmpQueries +} diff --git a/scripts/matrix_testing/GetTestDirectory.ps1 b/scripts/PSCodingStandards/Get-TestDirectory.ps1 similarity index 56% rename from scripts/matrix_testing/GetTestDirectory.ps1 rename to scripts/PSCodingStandards/Get-TestDirectory.ps1 index bd25ff7c07..341cb3d7d9 100644 --- a/scripts/matrix_testing/GetTestDirectory.ps1 +++ b/scripts/PSCodingStandards/Get-TestDirectory.ps1 @@ -1,8 +1,12 @@ -function Get-Test-Directory { +function Get-TestDirectory { param( [Parameter(Mandatory)] [object] - $RuleObject + $RuleObject, + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language ) if ($RuleObject.shared_implementation_short_name) { @@ -17,6 +21,12 @@ function Get-Test-Directory { elseif ($RuleObject.__memberof_suite -eq "CERT-C++") { $standardString = "cert" } + elseif ($RuleObject.__memberof_suite -eq "CERT-C") { + $standardString = "cert" + } + elseif ($RuleObject.__memberof_suite -eq "MISRA-C-2012") { + $standardString = "misra" + } else { throw "Unknown standard $($RuleObject.__memberof_suite)" } @@ -24,5 +34,5 @@ function Get-Test-Directory { $ruleDir = $RuleObject.__memberof_rule } - return Join-Path (Join-Path (Join-Path (Join-Path "cpp" $standardString) "test") "rules") $ruleDir + return Join-Path (Join-Path (Join-Path (Join-Path $Language $standardString) "test") "rules") $ruleDir } diff --git a/scripts/PSCodingStandards/README.md b/scripts/PSCodingStandards/README.md new file mode 100644 index 0000000000..633dd42ee0 --- /dev/null +++ b/scripts/PSCodingStandards/README.md @@ -0,0 +1,51 @@ +# Powershell Automation Library + +To use this on the command line, do: + +``` +Import-Module -Name .\scripts\PSCodingStandards\CodingStandards +``` + +To use this in your scripts you can do: + +``` +Import-Module -Name "$PSScriptRoot\..\PSCodingStandards\CodingStandards" +``` + +# Summary of Available Commands + + +**Get all the rules in a particular suite and language** + +``` +Get-RulesInSuite -Language c -Suite cert-c +``` + +Example: Get all rules in a suite with severity 'error'. + +``` +Get-RulesInSuite -Language c -Suite cert-c | Where-Object { $_.severity -eq 'error' } +``` + +**Get All Packages for a Language** + +``` +Get-Packages -Language c +``` + +**Get Rules in the IO package for a particular suite and language** + +``` +Get-RulesInPackageAndSuite -Suite cert-c -Package (Get-Packages -Language c | Where-Object { $_.BaseName -eq "IO" }) +``` + +**Get The Test Directory For Queries With Severity Error In autosar** + +``` +(Get-RulesInSuite -Language cpp -Suite autosar | Where-Object { $_.severity -eq 'error' }) | ForEach-Object { Get-TestDirectory -Language c -RuleObject $_ } +``` + +**Get the Root of Coding Standards** +``` +Get-RepositoryRoot +``` \ No newline at end of file diff --git a/scripts/matrix_testing/TestProgramInstalled.ps1 b/scripts/PSCodingStandards/Test-ProgramInstalled.ps1 similarity index 86% rename from scripts/matrix_testing/TestProgramInstalled.ps1 rename to scripts/PSCodingStandards/Test-ProgramInstalled.ps1 index d12e95727a..de73cd5d17 100644 --- a/scripts/matrix_testing/TestProgramInstalled.ps1 +++ b/scripts/PSCodingStandards/Test-ProgramInstalled.ps1 @@ -1,4 +1,4 @@ -function Test-Program-Installed { +function Test-ProgramInstalled { param( [Parameter(Mandatory)] [string] diff --git a/scripts/build_test_database.py b/scripts/build_test_database.py index a6cf6e9547..3f8acde999 100644 --- a/scripts/build_test_database.py +++ b/scripts/build_test_database.py @@ -4,19 +4,27 @@ import subprocess import json -if len(sys.argv) < 3: - print ("Usage: build_test_database.py STANDARD RULE", file=sys.stderr) +if len(sys.argv) < 4: + print ("Usage: build_test_database.py LANGUAGE STANDARD RULE", file=sys.stderr) exit(1) -STANDARD=sys.argv[1] -RULE=sys.argv[2] +LANGUAGE=sys.argv[1] +STANDARD=sys.argv[2] +RULE=sys.argv[3] if shutil.which("codeql") is None: print ("Please install codeql.", file=sys.stderr) exit(1) -if shutil.which("clang++") is None: - print ("Please install clang++.", file=sys.stderr) +if LANGUAGE == "cpp": + compiler = "clang++" +elif LANGUAGE == "c": + compiler = "clang" +else: + exit(f"Unknown language {LANGUAGE}") + +if shutil.which(compiler) is None: + print (f"Please install {compiler}", file=sys.stderr) exit(1) @@ -30,11 +38,11 @@ # check the standard -if not os.path.exists(f"cpp/{STANDARD}"): +if not os.path.exists(f"{LANGUAGE}/{STANDARD}"): print (f"Standard {STANDARD} doesn't exist.", file=sys.stderr) exit(1) -if not os.path.exists(f"cpp/{STANDARD}/test/rules/{RULE}"): +if not os.path.exists(f"{LANGUAGE}/{STANDARD}/test/rules/{RULE}"): print (f"Rule {RULE} within standard {STANDARD} doesn't exist.", file=sys.stderr) exit(1) @@ -44,15 +52,19 @@ CODEQL_VERSION=res_json["version"] # get the list of cpp files -all_files = os.listdir(f"cpp/{STANDARD}/test/rules/{RULE}/") +all_files = os.listdir(f"{LANGUAGE}/{STANDARD}/test/rules/{RULE}/") # make them into a string argument -FILES = ' '.join([f for f in all_files if f.endswith('.cpp')]) +if LANGUAGE == "cpp": + FILES = ' '.join([f for f in all_files if f.endswith('.cpp')]) + BUILD_COMMAND=f"clang++ -std=c++14 -fsyntax-only {FILES}" -BUILD_COMMAND=f"clang++ -std=c++14 -fsyntax-only {FILES}" +elif LANGUAGE == "c": + FILES = ' '.join([f for f in all_files if f.endswith('.c')]) + BUILD_COMMAND=f"clang -fsyntax-only {FILES}" ITERATION=0 while os.path.exists(f"databases/{RULE}+{ITERATION}@{CODEQL_VERSION}"): ITERATION = ITERATION + 1 -os.system(f"codeql database create -l cpp -s cpp/{STANDARD}/test/rules/{RULE} --command=\"{BUILD_COMMAND}\" databases/{RULE}+{ITERATION}@{CODEQL_VERSION}") +os.system(f"codeql database create -l cpp -s {LANGUAGE}/{STANDARD}/test/rules/{RULE} --command=\"{BUILD_COMMAND}\" databases/{RULE}+{ITERATION}@{CODEQL_VERSION}") diff --git a/scripts/create_language_matrix.py b/scripts/create_language_matrix.py new file mode 100644 index 0000000000..96a725edd5 --- /dev/null +++ b/scripts/create_language_matrix.py @@ -0,0 +1,24 @@ +import json +import os +from pathlib import Path + +config_file_path = Path(__file__).parent.parent.joinpath('supported_codeql_configs.json') + +with open(config_file_path, "r") as config_file: + json_data = json.load(config_file) + + matrix = [] + + # foreach language, merge in the existing metadata + for e in json_data["supported_language"]: + for c in json_data["supported_environment"]: + pass + #print(f"lang={e}, env={c}") + # + data = e + data.update(c) + matrix.append(data) + + print(json.dumps(matrix)) + + diff --git a/scripts/documentation/generate_iso26262_docs.py b/scripts/documentation/generate_iso26262_docs.py index 28098776b2..b011adf4e0 100644 --- a/scripts/documentation/generate_iso26262_docs.py +++ b/scripts/documentation/generate_iso26262_docs.py @@ -16,69 +16,54 @@ """ parser = ArgumentParser(description=help_statement) -parser.add_argument("output_directory", - help="the directory where the html files should be written") +parser.add_argument("output_directory", help="the directory where the html files should be written") args = parser.parse_args() output_directory = Path(args.output_directory) if os.path.exists(output_directory): - print("Error: output directory '" + str(output_directory) + "' exists.") - sys.exit(1) + print("Error: output directory '" + str(output_directory) + "' exists.") + sys.exit(1) output_directory.mkdir(parents=True) repo_root = Path(__file__).parent.parent.parent -env = Environment(loader=FileSystemLoader(Path(__file__).parent.joinpath( - "templates")), trim_blocks=True, lstrip_blocks=True) - +env = Environment(loader=FileSystemLoader(Path(__file__).parent.joinpath("templates")), trim_blocks=True, lstrip_blocks=True) def load_file(file): with open(file, 'r', errors='ignore') as f: return f.read() - def generate_html(markdown_file, html_output_file): - """ - Load the given Markdown file in GFM, and produce a HTML representation at the `html_output_file`. - """ - text = load_file(markdown_file) - try: - # Use the GitHub API to convert a GFM file to HTML - data = json.dumps({'text': text, 'mode': 'gfm'}, - ensure_ascii=False).encode('utf-8') - response = requests.post("https://api.github.com/markdown", - data=data, headers={'Accept': 'application/vnd.github.v3+json'}) - - # Throw an exception for a non 2XX status code - response.raise_for_status() - - # Ensure the directory exists for the output file - html_output_file.parent.mkdir(exist_ok=True, parents=True) - - # The HTML returned by GitHub is just the body. Render it within a HTML template that includes - # a stylesheet and html/head/body tags. - html_output = env.get_template("rendered_markdown.html.template").render( - markdown_body=response.text, title=markdown_file.name) - # Write the HTML page to the output file - with open(html_output_file, "w", newline="\n") as f: - f.write(html_output) - except HTTPError as http_err: - print("Error: could not process markdown file '" + - str(markdown_file) + "'.") - print(f'HTTP error occurred: {http_err}') - except Exception as err: - print("Error: could not process markdown file '" + - str(markdown_file) + "'.") - print(f'Other error occurred: {err}') - + """ + Load the given Markdown file in GFM, and produce a HTML representation at the `html_output_file`. + """ + text = load_file(markdown_file) + try: + # Use the GitHub API to convert a GFM file to HTML + data = json.dumps({'text': text, 'mode': 'gfm'}, ensure_ascii=False).encode('utf-8') + response = requests.post("https://api.github.com/markdown", data=data, headers={'Accept': 'application/vnd.github.v3+json'}) + + # Throw an exception for a non 2XX status code + response.raise_for_status() + + # Ensure the directory exists for the output file + html_output_file.parent.mkdir(exist_ok=True, parents=True) + + # The HTML returned by GitHub is just the body. Render it within a HTML template that includes + # a stylesheet and html/head/body tags. + html_output = env.get_template("rendered_markdown.html.template").render(markdown_body=response.text, title=markdown_file.name) + # Write the HTML page to the output file + with open(html_output_file, "w", newline="\n") as f: + f.write(html_output) + except HTTPError as http_err: + print("Error: could not process markdown file '" + str(markdown_file) + "'.") + print(f'HTTP error occurred: {http_err}') + except Exception as err: + print("Error: could not process markdown file '" + str(markdown_file) + "'.") + print(f'Other error occurred: {err}') # Convert each of the relevant markdown files in turn -for markdown_file in ["docs/development_handbook.md", "docs/user_manual.md", "docs/iso_26262_tool_qualification.md", ".github/pull_request_template.md"]: - output_file = Path(markdown_file) - if output_file.parts[0][0] == '.': - output_file = Path(output_file.parts[0][1:]).joinpath( - *output_file.parts[1:]) - generate_html(repo_root.joinpath(markdown_file), - output_directory.joinpath(output_file).with_suffix(".html")) +for markdown_file in ["development_handbook.md", "docs/user_manual.md", "docs/iso_26262_tool_qualification.md", ".github/pull_request_template.md"]: + generate_html(repo_root.joinpath(markdown_file), output_directory.joinpath(markdown_file).with_suffix(".html")) diff --git a/scripts/generate_metadata/generate_metadata_for_language.py b/scripts/generate_metadata/generate_metadata_for_language.py new file mode 100644 index 0000000000..60c45ea3e6 --- /dev/null +++ b/scripts/generate_metadata/generate_metadata_for_language.py @@ -0,0 +1,76 @@ +from argparse import ArgumentParser +from jinja2 import Environment, FileSystemLoader +import os +from pathlib import Path + +help_statement = """ +A tool for generating the language specific RuleMetadata.qll files. This tool +will generate a RuleMetadata.qll file in the +`/common/src/codingstandards//exclusions/` directory. + +If the files already exist: + - The metadata of the query file will be overwritten with the new metadata +""" +# Mapping of concrete language to QL Language +ql_language_mappings = { + "cpp": "cpp", + "c": "cpp" +} + +parser = ArgumentParser(description=help_statement) +parser.add_argument("language_name", help="the language of the package") +args = parser.parse_args() + +language_name = args.language_name + +if not language_name in ql_language_mappings: + exit(f"Unsupported language '{language_name}'") +else: + ql_language_name = ql_language_mappings[language_name] + +repo_root = Path(__file__).parent.parent.parent +rule_packages_file_path = repo_root.joinpath("rule_packages") +rule_package_file_path = rule_packages_file_path.joinpath(language_name) + +exclusions_path = repo_root.joinpath(ql_language_name, "common", "src", "codingstandards", ql_language_name, "exclusions", language_name) +# create the directories if they don't already exist. +os.makedirs(exclusions_path, exist_ok=True) + +metdata_data_file_path = repo_root.joinpath(exclusions_path, "RuleMetadata.qll") + +env = Environment(loader=FileSystemLoader(Path(__file__).parent.joinpath( + "templates")), trim_blocks=True, lstrip_blocks=True) + +packages = [] + + +valid_package_names = [] +# Get all of the packages, filtering out any that don't have queries +for package_file in rule_package_file_path.glob('*.json'): + package_name = package_file.name.split('.')[0] + valid_package_names.append(package_name) + +# Get all of the packages, filtering out any that don't have queries +for package_file in exclusions_path.glob('*.qll'): + package_name = package_file.name.split('.')[0] + + if package_name == "RuleMetadata": + continue + + if not package_name in valid_package_names: + print(f"Skipping unknown possible package library {str(package_file)}") + continue + + print(f"Reading package data for package {package_name}") + packages.append(package_name) + +packages = sorted(packages) +metadata_template = env.get_template("rulemetadata.qll.template") + +print(f"Writing out query help file to {str(metdata_data_file_path)}") + +output = metadata_template.render( + ql_language=ql_language_name, language_name=language_name, packages=packages) + +with open(metdata_data_file_path, "w", newline="\n") as f: + f.write(output) diff --git a/scripts/generate_metadata/templates/rulemetadata.qll.template b/scripts/generate_metadata/templates/rulemetadata.qll.template new file mode 100644 index 0000000000..802fa44641 --- /dev/null +++ b/scripts/generate_metadata/templates/rulemetadata.qll.template @@ -0,0 +1,27 @@ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ +import {{ ql_language }} +import codingstandards.{{ ql_language }}.exclusions.RuleMetadata +//** Import packages for this language **/ +{% for package in packages %} +import {{ package }} +{% endfor %} + +/** The TQuery type representing this language * */ +{% if packages | length == 1 %} +newtype T{{ language_name.upper() }}Query = T{{ packages[0] }}PackageQuery({{ packages[0] }}Query q) +{% else %} +newtype T{{ language_name.upper() }}Query = + {% for package in packages %} + T{{ package }}PackageQuery({{ package }}Query q){% if not loop.last %} or +{% endif %}{% endfor %} + +{% endif %} + +/** The metadata predicate * */ +predicate isQueryMetadata(Query query, string queryId, string ruleId) { + {% for package in packages %} + is{{ package }}QueryMetadata(query, queryId, ruleId){% if not loop.last %} or + {% endif %}{% endfor %} + +} + diff --git a/scripts/generate_rules/coding_standards_utils.py b/scripts/generate_rules/coding_standards_utils.py new file mode 100644 index 0000000000..454f7c0a70 --- /dev/null +++ b/scripts/generate_rules/coding_standards_utils.py @@ -0,0 +1,99 @@ +import re + +def split_camel_case(short_name): + """Split a camel case string to a list.""" + matches = re.finditer( + ".+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)", short_name) + return [m.group(0) for m in matches] + + +def standard_tag(standard_short_name, key, value): + """Create a CodeQL tag for the given standard and property name""" + return ( + "external/" + + standard_short_name + + "/" + + key.replace("_", "-").replace(" ", "-").lower() + + (("/" + value.replace("_", "-").replace(" ", "-").lower()) if value else "") + ) + + +def description_line_break(description): + """Split the description into a list of lines of no more than 84 characters""" + if len(description) < 85: + return [description] + else: + description_line = description[0:85] + # Reports the last space, or -1 + last_space = description_line.rfind(" ") + # If last space is -1, then we lose the extra character as required + description_line = description_line[0:last_space] + # Use recursion to calculate the lines in the tail of the string + return [description_line] + description_line_break(description[(len(description_line) + 1):]) + + +def write_template(template, args, package_name, file): + """Render the template with the given args, and write it to the file using \n newlines.""" + output = template.render(args, package_name=package_name) + with open(file, "w", newline="\n") as f: + f.write(output) + + +def write_exclusion_template(template, args, packagename, language_name, file): + """Render the template with the given args, and write it to the file using \n newlines.""" + output = template.render( + data=args, package_name=packagename, language_name=language_name) + + with open(file, "w", newline="\n") as f: + f.write(output) + +def extract_metadata_from_query(rule_id, title, q, rule_query_tags, language_name, ql_language_name, standard_name, standard_short_name, standard_metadata, anonymise): + + metadata = q.copy() + + # Add rule properties to the query dict, ready for template generation + metadata["standard_name"] = standard_name + metadata["standard_short_name"] = standard_short_name + metadata["rule_id"] = rule_id + metadata["rule_title"] = title + metadata["tags"].extend(rule_query_tags) + metadata["language_name"] = language_name + metadata["ql_language_name"] = ql_language_name + + metadata["shortname_camelcase"] = metadata["short_name"][0].lower( + ) + metadata["short_name"][1:] + + # short id generated from short name + metadata["short_id"] = "-".join([c.lower() + for c in split_camel_case(metadata["short_name"])]) + # set up model for exclusions + exclusion_model = {} + # queryid currently assumes c or c++ queries + exclusion_model["queryid"] = f"{language_name}/{standard_short_name}/{metadata['short_id']}" + exclusion_model["ruleid"] = rule_id + exclusion_model["queryname"] = metadata["short_name"] + exclusion_model["queryname_camelcase"] = metadata["short_name"][0].lower( + ) + metadata["short_name"][1:] + + if not "kind" in metadata: + # default to problem if not specified + metadata["kind"] = "problem" + # separate description into multiple lines + metadata["description"] = description_line_break( + metadata["description"] if "description" in metadata else metadata["rule_title"]) + + # Anonymise properties, if required + if anonymise: + metadata["rule_title"] = metadata["short_name"] + metadata["description"] = [metadata["short_name"] + ] if anonymise else metadata["description"] + metadata["name"] = metadata["short_name"] + + if not standard_name in standard_metadata: + exit(f"Unsupported standard '{standard_name}'") + + metadata.update(standard_metadata[standard_name]) + + + + return metadata, exclusion_model diff --git a/scripts/generate_rules/generate_package_description.py b/scripts/generate_rules/generate_package_description.py index 2ffeda075b..d3890e230f 100644 --- a/scripts/generate_rules/generate_package_description.py +++ b/scripts/generate_rules/generate_package_description.py @@ -7,13 +7,13 @@ import sys help_statement =""" -Usage: {script_name} +Usage: {script_name} A tool for generating a rule package description, in JSON format. The rules.csv file at the root of this repository is processed, and rules with a matching -package name are processed and used to generate a "rule package description" file in the -'rule_packages' directory, using the name of the package. +language and package name are processed and used to generate a "rule package description" +file in the 'rule_packages' directory, using the name of the package. The file will contain a JSON dictionary for each standard where the key is the rule ID and the value is a dictionary describing the rule metadata. The dictionary will also contain a @@ -30,6 +30,7 @@ If the file already exists, it will not be overwritten. Arguments: + - the programming language of the package (currently 'cpp' or 'c') - the name of the package to generate a package file for. """ @@ -37,10 +38,11 @@ print(help_statement.format(script_name=sys.argv[0])) sys.exit(0) -package_name = sys.argv[1] +language_name = sys.argv[1] +package_name = sys.argv[2] repo_root = Path(__file__).parent.parent.parent rules_file_path = repo_root.joinpath('rules.csv') -rule_packages_file_path = repo_root.joinpath('rule_packages') +rule_packages_file_path = repo_root.joinpath('rule_packages', language_name) if not os.path.isdir(rule_packages_file_path): os.mkdir(rule_packages_file_path) rule_package_file_path = rule_packages_file_path.joinpath(package_name + ".json") @@ -91,18 +93,19 @@ def generate_short_name(title): # Skip header row next(rules_reader, None) for rule in rules_reader: - standard = rule[0] - rule_id = rule[1] - queryable = rule[2] - obligation_level = rule[3] - enforcement_level = rule[4] - allocated_targets = rule[5] - rule_title = rule[6] - similar_query = rule[7] - package = rule[8] - difficulty = rule[9] - # Find all rules in the given package - if rule[8] == package_name: + language = rule[0] + standard = rule[1] + rule_id = rule[2] + queryable = rule[3] + obligation_level = rule[4] + enforcement_level = rule[5] + allocated_targets = rule[6] + rule_title = rule[7] + similar_query = rule[8] + package = rule[9] + difficulty = rule[10] + # Find all rules in the given language and package + if language == language_name and package == package_name: if not queryable == "Yes": print("Error: " + standard + " " + rule_id + " is marked as part of package " + package_name + " but is not marked as queryable.") sys.exit(1) diff --git a/scripts/generate_rules/generate_package_files.py b/scripts/generate_rules/generate_package_files.py index 54589ff9da..f9ba191f14 100644 --- a/scripts/generate_rules/generate_package_files.py +++ b/scripts/generate_rules/generate_package_files.py @@ -6,18 +6,24 @@ from pathlib import Path import re import sys +import subprocess +from coding_standards_utils import * +# +# PS Oneliner for regenerating a language: +# Get-ChildItem .\rule_packages\cpp\*.json | ForEach-Object { python .\scripts\generate_rules\generate_package_files.py cpp $_.BaseName } +# help_statement = """ A tool for generating query related files, given a package description in JSON format. -The JSON file at /rule_packages/.json is loaded, and for each +The JSON file at /rule_packages//.json is loaded, and for each entry in the `queries` array for each rule, we generate the following: - Query file in //src/rules//.ql - Query help file in //src/rules//.qhelp - Implementation section in //src/rules//-implementation.xml - Test reference in //test//.qlref - - Test file in //test//test.cpp + - Test file in //test//test. If the files already exist: - The metadata of the query file will be overwritten with the new metadata @@ -30,6 +36,32 @@ modify a query short name, first rename the relevant files manually, then re-run this script, ensuring that the package description has also been updated. """ +######################################################## +# Configuration Data +######################################################## +ql_language_mappings = { + "cpp": "cpp", + "c": "cpp" +} + +standard_metadata = { + "CERT-C++" : { + "standard_title" : "CERT-C++", + "standard_url" : "https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682" + }, + "AUTOSAR" : { + "standard_title" : "AUTOSAR: Guidelines for the use of the C++14 language in critical and safety-related systems", + "standard_url" : "https://www.autosar.org/fileadmin/user_upload/standards/adaptive/19-11/AUTOSAR_RS_CPP14Guidelines.pdf" + }, + "CERT-C" : { + "standard_title" : "CERT-C", + "standard_url" : "https://wiki.sei.cmu.edu/confluence/display/c" + }, + "MISRA-C-2012" : { + "standard_title" : "MISRA-C:2012 Guidelines for the use of the C language in critical systems", + "standard_url" : "https://www.misra.org.uk/" + } +} parser = ArgumentParser(description=help_statement) parser.add_argument( @@ -40,65 +72,138 @@ default=False, help="create anonymized versions of the queries, without identifying rule information", ) +parser.add_argument("language_name", help="the language of the package") parser.add_argument( "package_name", help="the name of the package to generate query files for") +######################################################## -args = parser.parse_args() +args = parser.parse_args() +language_name = args.language_name.lower() package_name = args.package_name + +# validate langauge +if not language_name in ql_language_mappings: + exit(f"Unsupported language '{language_name}'") +else: + ql_language_name = ql_language_mappings[language_name] + +# set up some basic paths repo_root = Path(__file__).parent.parent.parent rule_packages_file_path = repo_root.joinpath("rule_packages") rule_package_file_path = rule_packages_file_path.joinpath( - package_name + ".json") + language_name, package_name + ".json") env = Environment(loader=FileSystemLoader(Path(__file__).parent.joinpath( "templates")), trim_blocks=True, lstrip_blocks=True) -def split_camel_case(short_name): - """Split a camel case string to a list.""" - matches = re.finditer( - ".+?(?:(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|$)", short_name) - return [m.group(0) for m in matches] - -def standard_tag(standard_short_name, key, value): - """Create a CodeQL tag for the given standard and property name""" - return ( - "external/" - + standard_short_name - + "/" - + key.replace("_", "-").replace(" ", "-").lower() - + (("/" + value.replace("_", "-").replace(" ", "-").lower()) if value else "") - ) +def write_shared_implementation(package_name, rule_id, query, language_name, ql_language_name, common_src_pack_dir, common_test_pack_dir): -def description_line_break(description): - """Split the description into a list of lines of no more than 84 characters""" - if len(description) < 85: - return [description] - else: - description_line = description[0:85] - # Reports the last space, or -1 - last_space = description_line.rfind(" ") - # If last space is -1, then we lose the extra character as required - description_line = description_line[0:last_space] - # Use recursion to calculate the lines in the tail of the string - return [description_line] + description_line_break(description[(len(description_line) + 1):]) + shared_impl_dir_name = query["shared_implementation_short_name"].lower() + shared_impl_dir = common_src_pack_dir.joinpath( + "codingstandards", + ql_language_name, + "rules", + shared_impl_dir_name + ) -def write_template(template, args, package_name, file): - """Render the template with the given args, and write it to the file using \n newlines.""" - output = template.render(args, package_name=package_name) - with open(file, "w", newline="\n") as f: - f.write(output) + shared_impl_dir.mkdir(exist_ok=True, parents=True) + shared_impl_query_library_path = shared_impl_dir.joinpath( + query["shared_implementation_short_name"] + ".qll") + + # + # Write out the implementation. Implementations are + # always stored in the `ql_langauge_name` directory. + # + if not shared_impl_query_library_path.exists(): + + if len(query["short_name"]) > 50: + exit(f"Error: {query['short_name']} has more than 50 characters.") + + shared_library_template = env.get_template( + "shared_library.ql.template" + ) + + print(f"{rule_id}: Writing out shared implementation file to {str(shared_impl_query_library_path)}") + + write_template( + shared_library_template, + query, + package_name, + shared_impl_query_library_path + ) + else: + print(f"{rule_id}: Skipping writing shared implementation file to {str(shared_impl_query_library_path)}") + # Write out the test. Test are always stored under the `language_name` + # directory. + shared_impl_test_dir = common_test_pack_dir.joinpath( + "rules", + shared_impl_dir_name + ) -def write_exclusion_template(template, args, packagename, file): - """Render the template with the given args, and write it to the file using \n newlines.""" - output = template.render(data=args, package_name=packagename) + shared_impl_test_dir.mkdir(exist_ok=True, parents=True) - with open(file, "w", newline="\n") as f: - f.write(output) + # Generate test query file + shared_impl_test_query_path = shared_impl_test_dir.joinpath( + f"{query['shared_implementation_short_name']}.ql" + ) + + with open(shared_impl_test_query_path, "w", newline="\n") as f: + f.write("// GENERATED FILE - DO NOT MODIFY\n") + f.write( + "import " + + str(shared_impl_query_library_path.relative_to(common_src_pack_dir).with_suffix('')) + .replace("\\", "/") + .replace("/", ".") + + "\n" + ) + + # Create an empty test file, if one doesn't already exist + shared_impl_test_dir.joinpath( + "test." + language_name).touch() + + # Add an empty expected results file - this makes it possible to see the results the + # first time you run the test in VS Code + expected_results_file = shared_impl_test_dir.joinpath( + query["shared_implementation_short_name"] + ".expected") + if not expected_results_file.exists(): + with open(expected_results_file, "w", newline="\n") as f: + f.write( + "No expected results have yet been specified") + + # Add a testref file for this query, that refers to the shared library + test_ref_file = test_src_dir.joinpath( + query["short_name"] + ".testref") + with open(test_ref_file, "w", newline="\n") as f: + f.write(str(shared_impl_test_query_path.relative_to( + repo_root)).replace("\\", "/")) + + +def write_non_shared_testfiles(query, language_name, query_path, test_src_dir, src_pack_dir): + # Add qlref test file + print( + rule_id + ": Writing out query test files to " + str(test_src_dir)) + with open(test_src_dir.joinpath(query["short_name"] + ".qlref"), "w", newline="\n") as f: + f.write(str(query_path.relative_to( + src_pack_dir)).replace("\\", "/")) + + # Create an empty test file, if one doesn't already exist + test_src_dir.joinpath(f"test.{language_name}").touch() + + # Add an empty expected results file - this makes it possible to see the results the + # first time you run the test in VS Code + expected_results_file = test_src_dir.joinpath( + f"{query['short_name']}.expected" + ) + + if not expected_results_file.exists(): + with open(expected_results_file, "w", newline="\n") as f: + f.write( + "No expected results have yet been specified") try: @@ -129,13 +234,16 @@ def write_exclusion_template(template, args, packagename, file): # Identify the short name for the standard, used for directory and tag names standard_short_name = standard_name.split("-")[0].lower() - # Only support CPP for now + # Currently assumes that language_name is also the subdirectory name standard_dir = repo_root.joinpath( - "cpp").joinpath(standard_short_name) + language_name).joinpath(standard_short_name) # Identify common src and test packs - common_dir = repo_root.joinpath("cpp").joinpath("common") + common_dir = repo_root.joinpath( + ql_language_name).joinpath("common") common_src_pack_dir = common_dir.joinpath("src") - common_test_pack_dir = common_dir.joinpath("test") + # The language specific files always live under the commons for that + # language + common_test_pack_dir = repo_root.joinpath(language_name, "common", "test") # Identify the source pack for this standard src_pack_dir = standard_dir.joinpath("src") for rule_id, rule_details in rules.items(): @@ -156,45 +264,24 @@ def write_exclusion_template(template, args, packagename, file): rule_query_tags.append(standard_tag( standard_short_name, key, value)) - for query in rule_details["queries"]: - - # Add rule properties to the query dict, ready for template generation - query["standard_name"] = standard_name - query["standard_short_name"] = standard_short_name - query["rule_id"] = rule_id - query["rule_title"] = rule_details["title"] - query["tags"].extend(rule_query_tags) - query["anonymise"] = args.anonymise - query["shortname_camelcase"] = query["short_name"][0].lower( - ) + query["short_name"][1:] - # short id generated from short name - query["short_id"] = "-".join([c.lower() - for c in split_camel_case(query["short_name"])]) - # set up model for exclusions - exclusion_model = {} - exclusion_model["queryid"] = "cpp/" + \ - standard_short_name + "/" + query["short_id"] - exclusion_model["ruleid"] = rule_id - exclusion_model["queryname"] = query["short_name"] - exclusion_model["queryname_camelcase"] = query["short_name"][0].lower( - ) + query["short_name"][1:] + for q in rule_details["queries"]: + + # extract metadata and model + query, exclusion_model = extract_metadata_from_query( + rule_id, + rule_details["title"], + q, + rule_query_tags, + language_name, + ql_language_name, + standard_name, + standard_short_name, + standard_metadata, + args.anonymise + ) # add query to each dict exclusion_query.append(exclusion_model) - if not "kind" in query: - # default to problem if not specified - query["kind"] = "problem" - # separate description into multiple lines - query["description"] = description_line_break( - query["description"] if "description" in query else query["rule_title"]) - - # Anonymise properties, if required - if args.anonymise: - query["rule_title"] = query["short_name"] - query["description"] = [query["short_name"] - ] if args.anonymise else query["description"] - query["name"] = query["short_name"] - # Path to query file we want to generate or modify query_path = rule_src_dir.joinpath( query["short_name"] + ".ql") @@ -240,17 +327,7 @@ def write_exclusion_template(template, args, packagename, file): query_file.writelines(new_contents) # Ensure any trailing old data is deleted query_file.truncate() - - # Add some metadata for each supported standard - if standard_name == "CERT-C++": - query["standard_title"] = "CERT-C++" - query["standard_url"] = "https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=88046682" - elif standard_name == "AUTOSAR": - query["standard_title"] = "AUTOSAR: Guidelines for the use of the C++14 language in critical and safety-related systems" - query[ - "standard_url" - ] = "https://www.autosar.org/fileadmin/user_upload/standards/adaptive/19-11/AUTOSAR_RS_CPP14Guidelines.pdf" - + # Add qhelp file, overwriting if already present, since it's completely generated qhelp_template = env.get_template("template.qhelp") qhelp_path = rule_src_dir.joinpath( @@ -279,99 +356,37 @@ def write_exclusion_template(template, args, packagename, file): package_name, qhelp_std_path) if "shared_implementation_short_name" in query: - # This query uses a shared implementation, so generate the appropriate files - # Note: this will be called for each - shared_impl_dir_name = query["shared_implementation_short_name"].lower( - ) - - # Generate shared implementation library - shared_impl_dir = common_src_pack_dir.joinpath( - "codingstandards", "cpp", "rules", shared_impl_dir_name) - shared_impl_dir.mkdir(exist_ok=True, parents=True) - shared_impl_query_library_path = shared_impl_dir.joinpath( - query["shared_implementation_short_name"] + ".qll") - if not shared_impl_query_library_path.exists(): - if len(query["short_name"]) > 50: - print( - "Error: " + query["short_name"] + " has more than 50 characters. Query name should be less than 50 characters. ") - sys.exit(1) - shared_library_template = env.get_template( - "shared_library.ql.template") - print(rule_id + ": Writing out shared implementation file to " + - str(shared_impl_query_library_path)) - write_template( - shared_library_template, query, package_name, shared_impl_query_library_path) - else: - print(rule_id + ": Skipping writing shared implementation file to " + - str(shared_impl_query_library_path)) - - # Generate shared implementation test directory - shared_impl_test_dir = common_test_pack_dir.joinpath( - "rules", shared_impl_dir_name) - shared_impl_test_dir.mkdir(exist_ok=True, parents=True) - - # Generate test query file - shared_impl_test_query_path = shared_impl_test_dir.joinpath( - query["shared_implementation_short_name"] + ".ql") - with open(shared_impl_test_query_path, "w", newline="\n") as f: - f.write("// GENERATED FILE - DO NOT MODIFY\n") - f.write( - "import " - + str(shared_impl_query_library_path.relative_to(common_src_pack_dir).with_suffix('')) - .replace("\\", "/") - .replace("/", ".") - + "\n" - ) - - # Create an empty test file, if one doesn't already exist - shared_impl_test_dir.joinpath("test.cpp").touch() - - # Add an empty expected results file - this makes it possible to see the results the - # first time you run the test in VS Code - expected_results_file = shared_impl_test_dir.joinpath( - query["shared_implementation_short_name"] + ".expected") - if not expected_results_file.exists(): - with open(expected_results_file, "w", newline="\n") as f: - f.write( - "No expected results have yet been specified") - - # Add a testref file for this query, that refers to the shared library - test_ref_file = test_src_dir.joinpath( - query["short_name"] + ".testref") - with open(test_ref_file, "w", newline="\n") as f: - f.write(str(shared_impl_test_query_path.relative_to( - repo_root)).replace("\\", "/")) + write_shared_implementation(package_name, rule_id, query, language_name, ql_language_name, common_src_pack_dir, common_test_pack_dir) else: - # Add qlref test file - print( - rule_id + ": Writing out query test files to " + str(test_src_dir)) - with open(test_src_dir.joinpath(query["short_name"] + ".qlref"), "w", newline="\n") as f: - f.write(str(query_path.relative_to( - src_pack_dir)).replace("\\", "/")) - - # Create an empty test file, if one doesn't already exist - test_src_dir.joinpath("test.cpp").touch() - - # Add an empty expected results file - this makes it possible to see the results the - # first time you run the test in VS Code - expected_results_file = test_src_dir.joinpath( - query["short_name"] + ".expected") - if not expected_results_file.exists(): - with open(expected_results_file, "w", newline="\n") as f: - f.write( - "No expected results have yet been specified") - + write_non_shared_testfiles(query, language_name, query_path, test_src_dir, src_pack_dir) # Exclusions exclusions_template = env.get_template("exclusions.qll.template") common_exclusions_dir = common_src_pack_dir.joinpath( - "codingstandards", "cpp", "exclusions") + "codingstandards", + ql_language_name, + "exclusions") # assign package and sanitize package_name = package_name.replace("-", "") package_name = package_name[:1].upper() + package_name[1:] - exclusion_library_file = common_exclusions_dir.joinpath( - package_name + ".qll") + exclusion_library_file = common_exclusions_dir.joinpath(language_name, + package_name + ".qll") # write exclusions file print(package_name + ": Writing out exclusions file to " + str(exclusion_library_file)) - write_exclusion_template( - exclusions_template, exclusion_query, package_name, exclusion_library_file) + + os.makedirs(common_exclusions_dir.joinpath( + language_name), exist_ok=True) + + write_exclusion_template(exclusions_template, exclusion_query, + package_name, language_name, exclusion_library_file) + + +# After updating these files, the metadata should be regenerated +print("==========================================================") +print(f"Regenerating RuleMetadata.qll for {language_name.upper()}") +print("==========================================================") + +repo_root = Path(__file__).parent.parent.parent +update_metadata_path = repo_root.joinpath( + "scripts", "generate_metadata", "generate_metadata_for_language.py") +subprocess.run(["python", update_metadata_path, language_name]) diff --git a/scripts/generate_rules/templates/exclusions.qll.template b/scripts/generate_rules/templates/exclusions.qll.template index 98d229af70..2016871ea1 100644 --- a/scripts/generate_rules/templates/exclusions.qll.template +++ b/scripts/generate_rules/templates/exclusions.qll.template @@ -1,6 +1,7 @@ -//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. */ +//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ import cpp import RuleMetadata +import codingstandards.cpp.exclusions.RuleMetadata newtype {{ package_name }}Query = {% for query in data%} @@ -32,7 +33,7 @@ module {{ package_name }}Package { //autogenerate `Query` type result = // `Query` type for `{{query['queryname_camelcase']}}` query - T{{ package_name }}PackageQuery(T{{query['queryname']}}Query()) + TQuery{{ language_name.upper() }}(T{{ package_name }}PackageQuery(T{{query['queryname']}}Query())) }{% if not loop.last %} {% endif %}{% endfor %} diff --git a/scripts/generate_rules/templates/query.metadata.template b/scripts/generate_rules/templates/query.metadata.template index 798b7dc765..e7e6ead12f 100644 --- a/scripts/generate_rules/templates/query.metadata.template +++ b/scripts/generate_rules/templates/query.metadata.template @@ -1,5 +1,5 @@ /** - * @id cpp/{{ standard_short_name }}/{{ short_id }} + * @id {{ language_name }}/{{ standard_short_name }}/{{ short_id }} * @name {{ rule_id }}: {{ name }} * @description {{ description[0] }} {% for description_line in description[1:] %} diff --git a/scripts/generate_rules/templates/query.ql.template b/scripts/generate_rules/templates/query.ql.template index a7ca23c9b7..a387f41569 100644 --- a/scripts/generate_rules/templates/query.ql.template +++ b/scripts/generate_rules/templates/query.ql.template @@ -2,9 +2,9 @@ import cpp -import codingstandards.cpp.{{ standard_short_name }} +import codingstandards.{{ language_name }}.{{ standard_short_name }} {% if shared_implementation_short_name is defined %} -import codingstandards.cpp.rules.{{ shared_implementation_short_name.lower() }}.{{ shared_implementation_short_name }} +import codingstandards.{{ ql_language_name }}.rules.{{ shared_implementation_short_name.lower() }}.{{ shared_implementation_short_name }} class {{short_name}}Query extends {{shared_implementation_short_name}}SharedQuery { {{short_name}}Query() { diff --git a/scripts/generate_rules/templates/shared_library.ql.template b/scripts/generate_rules/templates/shared_library.ql.template index 93ac238635..24431edcc7 100644 --- a/scripts/generate_rules/templates/shared_library.ql.template +++ b/scripts/generate_rules/templates/shared_library.ql.template @@ -3,8 +3,8 @@ */ import cpp -import codingstandards.cpp.Customizations -import codingstandards.cpp.Exclusions +import codingstandards.{{ ql_language_name }}.Customizations +import codingstandards.{{ ql_language_name }}.Exclusions abstract class {{shared_implementation_short_name}}SharedQuery extends Query { } diff --git a/scripts/help/cert-help-extraction.py b/scripts/help/cert-cpp-help-extraction.py similarity index 70% rename from scripts/help/cert-help-extraction.py rename to scripts/help/cert-cpp-help-extraction.py index d5d87c5e7d..a8f81e240b 100644 --- a/scripts/help/cert-help-extraction.py +++ b/scripts/help/cert-cpp-help-extraction.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python import sys import requests from bs4 import BeautifulSoup @@ -6,19 +5,15 @@ import copy from pathlib import Path import hashlib -from urllib.parse import quote_plus, urlparse -import urllib.request -import re +from urllib.parse import quote_plus CERT_WIKI = "https://wiki.sei.cmu.edu" -RULES_LIST_C = "/confluence/display/c/2+Rules" -RULES_LIST_CPP = "/confluence/display/cplusplus/2+Rules" +RULES_LIST = "/confluence/display/cplusplus/2+Rules" script_path = Path(__file__) cache_path = script_path.parent.joinpath('.cache') cache_path.mkdir(exist_ok=True) repo_root = script_path.parent.parent.parent -rule_path = None def soupify(url: str) -> BeautifulSoup: @@ -28,7 +23,7 @@ def soupify(url: str) -> BeautifulSoup: cache_file = cache_path.joinpath(cache_key) if cache_file.exists(): with cache_file.open() as f: - content = f.read().replace(u'\xa0', u' ') + content = f.read() else: resp = requests.get(url) @@ -42,24 +37,8 @@ def soupify(url: str) -> BeautifulSoup: return BeautifulSoup(content, 'html.parser') -def get_rules_c(): - soup = soupify(f"{CERT_WIKI}{RULES_LIST_C}") - if soup == None: - return None - - rule_listing_start = soup.find( - "h1", string="Rule Listing") - rules = [] - for link in rule_listing_start.next_element.next_element.find_all('a'): - if '-C' in link.string: - rule, title = map(str.strip, link.string.split('.', 1)) - rules.append({'id': rule, 'title': title, 'link': link['href']}) - - return rules - - -def get_rules_cpp(): - soup = soupify(f"{CERT_WIKI}{RULES_LIST_CPP}") +def get_rules(): + soup = soupify(f"{CERT_WIKI}{RULES_LIST}") if soup == None: return None @@ -155,6 +134,7 @@ def text(e): SECTION_ELEMENTS = [e('example', none, any_block_element), e('fragment', none, any_block_element), + e('hr', none, none), e('include', any_of('hr'), none), e('overview', none, any_block_element), e('recommendation', none, any_block_element), @@ -191,8 +171,7 @@ def text(e): ELEMENTS = {e_tag(e): e for e in SECTION_ELEMENTS + BLOCK_ELEMENTS + LIST_ELEMENTS + TABLE_ELEMENTS + INLINE_ELEMENTS} -SUPPORTED_TAGS = list(ELEMENTS.keys()) + \ - ['body', 'h1', 'h2', 'h3', 'h4', 'h6', 'thead'] +SUPPORTED_TAGS = list(ELEMENTS.keys()) + ['body', 'h1', 'h2', 'h3', 'h4'] def is_code_table(tag): @@ -212,20 +191,14 @@ def is_navigation(node): return False -def transform_html(rule, soup): +def transform_html(soup): """Remove unsupported tags and attributes starting at node""" def helper(node): if isinstance(node, Tag): if node.name in SUPPORTED_TAGS: - # Fix a broken url present in many CERT-C pages - if node.name == 'a' and 'href' in node.attrs and node['href'] == "http://BB. Definitions#vulnerability": - node['href'] = "https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability" # Turn relative URLs into absolute URLS - elif node.name == 'a' and 'href' in node.attrs and node['href'].startswith("/confluence"): + if node.name == "a" and 'href' in node.attrs and node['href'].startswith("/confluence"): node['href'] = f"{CERT_WIKI}{node['href']}" - # Turn anchor references into absolute URLS - elif node.name == 'a' and 'href' in node.attrs and node['href'].startswith('#'): - node['href'] = f"{CERT_WIKI}{rule['link']}{node['href']}" # Percent encode exclude characters in fragments according to https://datatracker.ietf.org/doc/html/rfc2396#section-2.4.3 if node.name == 'a' and 'href' in node.attrs: href = node['href'] @@ -254,33 +227,37 @@ def helper(node): # Remove the navigation, we can only use the src attribute of the child because all other # attributes have been stripped if is_navigation(node): + if node.previous_sibling.name == 'hr': + node.previous_sibling.decompose() node.decompose() # Unwrap

    tags containing a list # Remove empty

    tags or tags containing a No-Break Space Unicode character representing a ` `. if node.name == "p" and (len(node.contents) == 0 or node.string == "\u00a0"): node.decompose() + # Remove non breaking spaces in headers + if node.name in ['h2', 'h3', 'h4']: + if len(node.contents) == 2 and node.contents[1].string == "\u00a0": + node.string = node.contents[0] # Smooth headers if node.name in ['h1', 'h2', 'h3', 'h4']: for child in node.contents: - if not text(child): + if not isNavigableString(child): child.unwrap() node.smooth() # Upgrade header levels :/ if node.name == 'h3' and node.string in ['Automated Detection', 'Related Vulnerabilities']: # print('Inconsistent header') node.name = 'h2' - # All

    should be in a table inside a single - if node.name == 'table': - for b in node.find_all('thead', Recursive=False): - b.unwrap() - for b in node.find_all('tbody', Recursive=False): - b.unwrap() - + # Wrap tr tags that are a direct child of a table without a tbody into a mandatory tbody + if node.name == 'table' and not node.tbody: tbody = soup.new_tag('tbody') for tr in node.find_all('tr', Recursive=False): - tbody.append(tr) + tbody.append(tr.extract()) node.append(tbody) + # Insert tr tags that are a direct child of a table with a tbody because are a result of an unwrapped thead + if node.name == 'table' and node.tbody and node.tr: + node.tbody.insert(0, node.tr.extract()) # Remove p tags from td and th tags if node.name in ['th', 'td'] and node.p: node.p.unwrap() @@ -289,22 +266,6 @@ def helper(node): node.decompose() if node.name == 'img' and 'data-macro-name' in node.attrs and node['data-macro-name'] == 'anchor': node.decompose() - # Retrieve Images - if node.name == 'img' and 'src' in node.attrs and node['src'].startswith("/confluence") and not node['src'].startswith("/confluence/plugins/"): - url = CERT_WIKI+node['src'] - filename = urlparse(url).path.split("/")[-1] - # exclude button arrows images - if not 'button_arrow' in filename: - full_name = repo_root.joinpath(rule_path, filename) - urllib.request.urlretrieve(url, full_name) - node['src'] = filename - # Unwrap , because can only contain text in QHelp - if node.name == 'code' and node.find_parent('a'): - node.unwrap() - # Swap containing , because can only contain text in QHelp - if node.name == 'a' and node.sup: - sup = node.sup.extract() - node.wrap(sup) # Swap containing , because can only contain text in QHelp if node.name == 'a' and node.strong: strong = node.strong.extract() @@ -330,14 +291,10 @@ def helper(node): # Replace with because in QLHelp
     is a block element while 
    with because in QLHelp is a block element while with because QLHelp doesn't support nested lists. if node.name == 'td' and node.ul: list_contents = ", ".join( - map(lambda n: n.string.lower() + n.string[1:] if n.string else '', node.ul.find_all('li'))).capitalize() + map(lambda n: n.string[0].lower() + n.string[1:], node.ul.find_all('li'))).capitalize() if not list_contents.endswith('.'): list_contents += '.' node.ul.replace_with(list_contents) @@ -346,32 +303,28 @@ def helper(node): for child in node.find_all('li', recursive=False): child.unwrap() node.unwrap() - # Replace
    • ...

    with the contents of the paragraph because QLHelp doesn't support paragraphs inside lists. - if node.name == 'p' and node.find_parent('li'): - node.unwrap() strip_attributes(node) - if node.name == 'h6': - node.name = 'p' else: node.unwrap() apply_post_order(soup.body, helper) def inject_versions(soup_with, soup_without): - def find_automated_detection_table(soup): - # Some help files use h2 and some use h3 - h = soup.find(text=re.compile("Automated Detection")) - return h.find_next('table') - def get_versions(): - table = find_automated_detection_table(soup_with) + # Some help files use h3 instead of :/ + h = soup_with.find(['h2', 'h3'], string="Automated Detection") + # Some help files use h2, but with additional content :/ + if not h: + for h2 in soup_with.find_all(['h2', 'h3']): + text = h2.contents[0] + if text.string == "Automated Detection": + h = h2 + break + if not h: + raise "Unable to find required 'Automated Detection' header" + table = h.next_sibling.table versions = [] - trs = [] - if table.thead: - trs.extend(table.thead.find_all('tr', Recursive=False)) - if table.tbody: - trs.extend(table.tbody.find_all('tr', Recursive=False)) - for tr in trs: + for tr in table.tbody.find_all('tr', Recursive=False): # Skip header row, if any if tr.th: continue @@ -379,31 +332,29 @@ def get_versions(): first_column = tr.td version_column = first_column.next_sibling - if version_column.div and version_column.div.div and version_column.div.div.p: - version = version_column.div.div.p.string - elif version_column.div and version_column.div.p: + if version_column.div and version_column.div.p: version = version_column.div.p.string elif version_column.div: version = version_column.div.string - elif version_column.p: - version = version_column.p.string - elif version_column.a: - version = version_column.a.string + elif (version_column.p and version_column.p.br) or version_column.br: + # No version information + version = "" + elif len(version_column.find_all(True)) > 0: + print(version_column) + raise "Unexpected version column" else: version = version_column.string - # replace None with the empty string - versions.append(version or '') + versions.append(version) return versions def set_versions(versions): - table = find_automated_detection_table(soup_without) + h = soup_without.find('h2', string="Automated Detection") + if not h: + print("Failed to find header 'Automated Detection'") + table = h.find_next('table') + i = 0 - trs = [] - if table.thead: - trs.extend(table.thead.find_all('tr', Recursive=False)) - if table.tbody: - trs.extend(table.tbody.find_all('tr', Recursive=False)) - for tr in trs: + for tr in table.tbody.find_all('tr', Recursive=False): # Skip header row, if any if tr.th: continue @@ -452,6 +403,10 @@ def aux(*args, **kwargs): return aux +def isNavigableString(t): + return isinstance(t, NavigableString) + + def get_help(rule): # print(rule) rule_view = soupify(f"{CERT_WIKI}{rule['link']}") @@ -465,36 +420,24 @@ def get_help(rule): return None soup.head.decompose() - transform_html(rule, soup) + transform_html(soup) inject_versions(rule_view, soup) qhelp_doc = convert2qhelp(soup) - # preserve whitespace when printing - qhelp_doc.preserve_whitespace_tags.update( - ['sample', 'code', 'strong', 'p', 'li']) return qhelp_doc.prettify() -rules_c = get_rules_c() -rules_cpp = get_rules_cpp() -if rules_c == None or rules_cpp == None: +rules = get_rules() +if rules == None: print("Failed to retrieve list of rules", file=sys.stdout) sys.exit(1) -for rule in get_rules_c(): - rule_path = repo_root.joinpath('c', 'cert', 'src', 'rules', rule['id']) - # only consider implemented rules - if rule_path.exists(): - for help_rule_file in rule_path.glob('*-standard.qhelp'): - print(f"ID: {rule['id']} url: {CERT_WIKI}{rule['link']}") - with help_rule_file.open('w') as f: - f.write(get_help(rule)) - -for rule in get_rules_cpp(): +for rule in rules: + print(f"ID: {rule['id']} url: {CERT_WIKI}{rule['link']}") + help = get_help(rule) rule_path = repo_root.joinpath('cpp', 'cert', 'src', 'rules', rule['id']) - # only consider implemented rules if rule_path.exists(): for help_rule_file in rule_path.glob('*-standard.qhelp'): - print(f"ID: {rule['id']} url: {CERT_WIKI}{rule['link']}") + print(f"Writing {help_rule_file}") with help_rule_file.open('w') as f: - f.write(get_help(rule)) \ No newline at end of file + f.write(help) diff --git a/scripts/matrix_testing/CompileFixTool.ps1 b/scripts/matrix_testing/CompileFixTool.ps1 index fe1d948307..ed4db02840 100755 --- a/scripts/matrix_testing/CompileFixTool.ps1 +++ b/scripts/matrix_testing/CompileFixTool.ps1 @@ -8,6 +8,11 @@ param( [Parameter(Mandatory = $false)] [string] $ReportDir = (Get-Location), + + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language, # The compiler to use. Valid values are 'clang' and 'arm-clang'. [Parameter(Mandatory)] @@ -16,18 +21,17 @@ param( $Configuration ) -. "$PSScriptRoot\GetTestDirectory.ps1" +Import-Module -Name "$PSScriptRoot\..\PSCodingStandards\CodingStandards" + . "$PSScriptRoot\NewDatabaseForRule.ps1" -. "$PSScriptRoot\GetRulesInSuite.ps1" . "$PSScriptRoot\Config.ps1" -. "$PSScriptRoot\TestProgramInstalled.ps1" -. "$PSScriptRoot\GetCompilerExecutable.ps1" +. "$PSScriptRoot\Get-CompilerExecutable.ps1" # # Verify All the Required CLI Tools are Installed # Write-Host "Checking 'codeql' program...." -NoNewline -Test-Program-Installed -Program "codeql" +Test-ProgramInstalled -Program "codeql" Write-Host -ForegroundColor ([ConsoleColor]2) "OK" $CODEQL_VERSION = (codeql version --format json | ConvertFrom-Json).version @@ -38,8 +42,8 @@ if (-Not $CODEQL_VERSION -eq $REQUIRED_CODEQL_VERSION) { } Write-Host -ForegroundColor ([ConsoleColor]2) "OK" -Write-Host "Checking '$(Get-CompilerExecutable -Configuration $Configuration)' program...." -NoNewline -Test-Program-Installed -Program (Get-CompilerExecutable -Configuration $Configuration) +Write-Host "Checking '$(Get-CompilerExecutable -Configuration $Configuration -Language $Language)' program...." -NoNewline +Test-ProgramInstalled -Program (Get-CompilerExecutable -Configuration $Configuration -Language $Language) Write-Host -ForegroundColor ([ConsoleColor]2) "OK" @@ -47,7 +51,7 @@ $allQueries = @() # load all the queries foreach ($s in $AVAILABLE_SUITES) { - $allQueries += Get-Rules-In-Suite -Suite $s + $allQueries += Get-RulesInSuite -Suite $s -Language $Language } $csv = Import-CSV $MatrixReport @@ -102,7 +106,7 @@ $ctr = 0 while ($true) { $q = Get-Query-From-Name -AllQueries $allQueries -RuleName $row.QUERY - $testDirectory = (Get-Test-Directory -RuleObject $q) + $testDirectory = (Get-TestDirectory -RuleObject $q -Language $Language) $testPath = Join-Path $testDirectory "test.cpp" $P = $PROMPT -f $row.QUERY, $row.SUITE, $row.PACKAGE, $row.RULE, $testPath, $TRIAGE.Length, $ctr, $failedQueries.Length @@ -112,7 +116,7 @@ $ctr = 0 if ($cmd -eq "1") { try { - New-Database-For-Rule -RuleName $row.RULE -RuleTestDir $testDirectory -Configuration $Configuration + New-Database-For-Rule -RuleName $row.RULE -RuleTestDir $testDirectory -Configuration $Configuration -Language $Language Write-Host -ForegroundColor ([ConsoleColor]2) "OK" } catch { diff --git a/scripts/matrix_testing/Config.ps1 b/scripts/matrix_testing/Config.ps1 index dbd13c4a2b..9d64e20452 100644 --- a/scripts/matrix_testing/Config.ps1 +++ b/scripts/matrix_testing/Config.ps1 @@ -1,16 +1,29 @@ $COMPILER_MAPPINGS = @{ - "clang" = "clang++"; - "armclang" = "armclang"; - "tiarmclang" = "tiarmclang"; + "cpp" = @{ + "clang" = "clang++"; + "armclang" = "armclang"; + "tiarmclang" = "tiarmclang"; + }; + + "c" = @{ + "clang" = "clang"; + }; } $COMPILER_ARGS = @{ - "clang" = "-std=c++14 -fsyntax-only"; - "armclang" = "-std=c++14 -fsyntax-only --target=arm-arm-none-eabi"; - "tiarmclang" = "-std=c++14 -fsyntax-only --target=arm-arm-none-eabi"; + "cpp" = @{ + "clang" = "-std=c++14 -fsyntax-only"; + "armclang" = "-std=c++14 -fsyntax-only --target=arm-arm-none-eabi"; + "tiarmclang" = "-std=c++14 -fsyntax-only --target=arm-arm-none-eabi"; + }; + + "c" = @{ + "clang" = "-fsyntax-only"; + }; + } -$AVAILABLE_SUITES = @("CERT-C++", "AUTOSAR") +$AVAILABLE_SUITES = @("CERT-C++", "AUTOSAR", "MISRA-C-2012", "CERT-C") $REQUIRED_CODEQL_VERSION = "2.6.3" diff --git a/scripts/matrix_testing/CreateMatrixTestReport.ps1 b/scripts/matrix_testing/CreateMatrixTestReport.ps1 index bb584004e1..2afc42e05a 100644 --- a/scripts/matrix_testing/CreateMatrixTestReport.ps1 +++ b/scripts/matrix_testing/CreateMatrixTestReport.ps1 @@ -114,6 +114,11 @@ param( [switch] $AllRules, + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language, + [Parameter(Mandatory = $false)] [string] $ReportDir = (Get-Location), @@ -136,9 +141,9 @@ param( $Configuration, # For a suite, the suites we support. Valid values are 'CERT-C++' and - # 'AUTOSAR'. + # 'AUTOSAR' and MISRA-C-2012 and CERT-C [Parameter(Mandatory, ParameterSetName = 'Suite')] - [ValidateSet("CERT-C++", "AUTOSAR")] + [ValidateSet("CERT-C++", "AUTOSAR", "MISRA-C-2012", "CERT-C")] [string] $SuiteName, @@ -197,10 +202,10 @@ param( $PackageName ) -. "$PSScriptRoot\TestProgramInstalled.ps1" -. "$PSScriptRoot\GetRulesInSuite.ps1" -. "$PSScriptRoot\GetCompilerExecutable.ps1" +Import-Module -Name "$PSScriptRoot\..\PSCodingStandards\CodingStandards" + . "$PSScriptRoot\CreateSummaryReport.ps1" +. "$PSScriptRoot\Get-CompilerExecutable.ps1" . "$PSScriptRoot\Config.ps1" $REPORT = @() @@ -215,7 +220,7 @@ $queriesToCheck = @() # load all the queries foreach ($s in $AVAILABLE_SUITES) { - $allQueries += Get-Rules-In-Suite -Suite $s + $allQueries += Get-RulesInSuite -Suite $s -Language $Language } # filter the set down based on the selections @@ -244,7 +249,7 @@ else { # Step 2: Verify All the Required CLI Tools are Installed # Write-Host "Checking 'codeql' program...." -NoNewline -Test-Program-Installed -Program "codeql" +Test-ProgramInstalled -Program "codeql" Write-Host -ForegroundColor ([ConsoleColor]2) "OK" $CODEQL_VERSION = (codeql version --format json | ConvertFrom-Json).version @@ -253,10 +258,10 @@ Write-Host "Checking 'codeql' version = $REQUIRED_CODEQL_VERSION...." -NoNewline if (-Not $CODEQL_VERSION -eq $REQUIRED_CODEQL_VERSION) { throw "Invalid CodeQL version $CODEQL_VERSION. Please install $REQUIRED_CODEQL_VERSION." } -Write-Host -ForegroundColor ([ConsoleColor]2) "OK" +Write-Host -ForegroundColor ([ConsoleColor]2) "OK" -Write-Host "Checking '$(Get-CompilerExecutable -Configuration $Configuration)' program...." -NoNewline -Test-Program-Installed -Program (Get-CompilerExecutable -Configuration $Configuration) +Write-Host "Checking '$(Get-CompilerExecutable -Configuration $Configuration -Language $Language)' program...." -NoNewline +Test-ProgramInstalled -Program (Get-CompilerExecutable -Configuration $Configuration -Language $Language) Write-Host -ForegroundColor ([ConsoleColor]2) "OK" # @@ -266,9 +271,11 @@ Write-Host -ForegroundColor ([ConsoleColor]2) "OK" # $jobRows = $queriesToCheck | ForEach-Object -ThrottleLimit $NumThreads -Parallel { - . "$using:PSScriptRoot\GetTestDirectory.ps1" + Import-Module -Name "$using:PSScriptRoot\..\PSCodingStandards\CodingStandards" + + #. "$using:PSScriptRoot\GetTestDirectory.ps1" . "$using:PSScriptRoot\NewDatabaseForRule.ps1" - . "$using:PSScriptRoot\ExecuteQueryAndDecodeAsJson.ps1" + $q = $_ @@ -278,33 +285,23 @@ $jobRows = $queriesToCheck | ForEach-Object -ThrottleLimit $NumThreads -Parallel $CurrentPackageName = $q.__memberof_package # for the report $row = @{ - "SUITE" = $CurrentSuiteName; - "PACKAGE" = $CurrentPackageName; - "RULE" = $CurrentRuleName; - "QUERY" = $CurrentQueryName; - "COMPILE_PASS" = $false; - "EXTRACTOR_PASS" = $false; - "EXTRACTOR_ERRORS" = ""; - "TEST_PASS" = $false ; - "TEST_DIFFERENCE" = ""; + "SUITE" = $CurrentSuiteName; + "PACKAGE" = $CurrentPackageName; + "RULE" = $CurrentRuleName; + "QUERY" = $CurrentQueryName; + "COMPILE_PASS" = $false; + "TEST_PASS" = $false + "TEST_DIFFERENCE" = "" } - Write-Host "Resolving pack 'codeql/cpp-queries'...." -NoNewline - $CODEQL_CPP_QUERIES_PATH = (codeql resolve qlpacks --format json | ConvertFrom-Json)."codeql/cpp-queries" - if ( -Not (Test-Path -Path $CODEQL_CPP_QUERIES_PATH -PathType Container) ) { - Write-Host "Could not resolve pack 'codeql/cpp-queries'. Please install the pack 'codeql/cpp-queries'." - return $row - } - Write-Host -ForegroundColor ([ConsoleColor]2) "OK" - Write-Host "====================[Rule=$CurrentRuleName,Suite=$CurrentSuiteName/Query=$CurrentQueryName]====================" - $testDirectory = (Get-Test-Directory -RuleObject $q) + $testDirectory = (Get-TestDirectory -RuleObject $q -Language $using:Language) Write-Host "Compiling database in $testDirectory..." -NoNewline try { - $db = New-Database-For-Rule -RuleName $CurrentRuleName -RuleTestDir $testDirectory -Configuration $using:Configuration + $db = New-Database-For-Rule -RuleName $CurrentRuleName -RuleTestDir $testDirectory -Configuration $using:Configuration -Language $using:Language Write-Host -ForegroundColor ([ConsoleColor]2) "OK" } catch { @@ -315,24 +312,7 @@ $jobRows = $queriesToCheck | ForEach-Object -ThrottleLimit $NumThreads -Parallel # output. } - $row["COMPILE_PASS"] = $true - Write-Host "Validating extractor results..." -NoNewline - - try { - $diagnostics = Execute-QueryAndDecodeAsJson -DatabasePath $db -QueryPath $diagnostic_query - }catch { - Write-Host -ForegroundColor ([ConsoleColor]4) $_Exception.Message - return $row - } - - if ( $diagnostics.'#select'.tuples.Length -eq 0 ) { - $row["EXTRACTOR_PASS"] = $true - Write-Host -ForegroundColor ([ConsoleColor]2) "OK" - } else { - Write-Host -ForegroundColor ([ConsoleColor]4) "FAILED" - $row["EXTRACTOR_ERRORS"] = $diagnostics | ConvertTo-Json -Depth 100 - } - + $row["COMPILE_PASS"] = $true Write-Host "Checking expected output..." # Note this technique uses so-called "wizard" settings to make it possible @@ -402,7 +382,7 @@ $jobRows | ForEach-Object { # Step 4: Create reports # -$fileTag = "$($Configuration.ToLower())-$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss")" +$fileTag = "$($Configuration.ToLower())-$Language-$(Get-Date -Format "yyyy-MM-dd_HH-mm-ss")" $reportOutputFile = Join-Path $ReportDir "MatrixTestReport-$fileTag.csv" $summaryReportOutputFile = Join-Path $ReportDir "MatrixTestReportSummary-$fileTag.csv" diff --git a/scripts/matrix_testing/ExecuteQueryAndDecodeAsJson.ps1 b/scripts/matrix_testing/ExecuteQueryAndDecodeAsJson.ps1 deleted file mode 100644 index 8240513deb..0000000000 --- a/scripts/matrix_testing/ExecuteQueryAndDecodeAsJson.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -function Execute-QueryAndDecodeAsJson() { - param([Parameter(mandatory)] - [string] - $DatabasePath, - [string] - $QueryPath - ) - - $bqrs = (Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid())) + ".bqrs" - if ( -Not (Test-Path -Path $QueryPath -PathType Leaf) ) { - throw "Could not resolve query: $QueryPath." - } - - codeql query run -q -o $bqrs -d $DatabasePath $QueryPath - if ( -Not $LASTEXITCODE -eq 0 ) { - throw "Failed to execute query: $QueryPath." - } - - $jsonResult = (Join-Path ([System.IO.Path]::GetTempPath()) ([System.Guid]::NewGuid())) + ".json" - codeql bqrs decode -q -o $jsonResult --format=json $bqrs - if ( -Not $LASTEXITCODE -eq 0 ) { - throw "Failed to decode results file $bqrs." - } - $result = Get-Content -Path $jsonResult | ConvertFrom-Json - - return $result -} diff --git a/scripts/matrix_testing/Get-CompilerArgs.ps1 b/scripts/matrix_testing/Get-CompilerArgs.ps1 new file mode 100644 index 0000000000..5ce7b52ab8 --- /dev/null +++ b/scripts/matrix_testing/Get-CompilerArgs.ps1 @@ -0,0 +1,12 @@ +. "$PSScriptRoot\Config.ps1" +function Get-CompilerArgs { + param([Parameter(Mandatory)] + [string] + $Configuration, + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language + ) + return $COMPILER_ARGS[$Language][$Configuration] +} \ No newline at end of file diff --git a/scripts/matrix_testing/Get-CompilerExecutable.ps1 b/scripts/matrix_testing/Get-CompilerExecutable.ps1 new file mode 100644 index 0000000000..9ca9bce889 --- /dev/null +++ b/scripts/matrix_testing/Get-CompilerExecutable.ps1 @@ -0,0 +1,12 @@ +. "$PSScriptRoot\Config.ps1" +function Get-CompilerExecutable { + param([Parameter(Mandatory)] + [string] + $Configuration, + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language + ) + return $COMPILER_MAPPINGS[$Language][$Configuration] +} \ No newline at end of file diff --git a/scripts/matrix_testing/GetCompilerArgs.ps1 b/scripts/matrix_testing/GetCompilerArgs.ps1 deleted file mode 100644 index a2d6898c09..0000000000 --- a/scripts/matrix_testing/GetCompilerArgs.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -. "$PSScriptRoot\Config.ps1" -function Get-CompilerArgs { - param([Parameter(Mandatory)] - [string] - $Configuration - ) - return $COMPILER_ARGS[$Configuration] -} \ No newline at end of file diff --git a/scripts/matrix_testing/GetCompilerExecutable.ps1 b/scripts/matrix_testing/GetCompilerExecutable.ps1 deleted file mode 100644 index 8f82c6f788..0000000000 --- a/scripts/matrix_testing/GetCompilerExecutable.ps1 +++ /dev/null @@ -1,8 +0,0 @@ -. "$PSScriptRoot\Config.ps1" -function Get-CompilerExecutable { - param([Parameter(Mandatory)] - [string] - $Configuration - ) - return $COMPILER_MAPPINGS[$Configuration] -} \ No newline at end of file diff --git a/scripts/matrix_testing/GetPackages.ps1 b/scripts/matrix_testing/GetPackages.ps1 deleted file mode 100644 index 39f993672a..0000000000 --- a/scripts/matrix_testing/GetPackages.ps1 +++ /dev/null @@ -1,4 +0,0 @@ -. "$PSScriptRoot\GetRepositoryRoot.ps1" -function Get-Packages { - return Get-ChildItem (Join-Path (Get-RepositoryRoot) "\rule_packages\*.json") -} \ No newline at end of file diff --git a/scripts/matrix_testing/GetRulesInSuite.ps1 b/scripts/matrix_testing/GetRulesInSuite.ps1 deleted file mode 100644 index 39a1761241..0000000000 --- a/scripts/matrix_testing/GetRulesInSuite.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -. "$PSScriptRoot\GetPackages.ps1" -. "$PSScriptRoot\GetRulesInPackageAndSuite.ps1" - -function Get-Rules-In-Suite { - param( - [Parameter(Mandatory)] - [string] - $Suite - ) - - $tmpQueries = @() - - foreach ($p in Get-Packages) { - Write-Host "Reading package: [$Suite/$($p.BaseName)]" - $tmpQueries += Get-Rules-In-Package-And-Suite -Package $p -Suite $Suite - } - - return $tmpQueries -} diff --git a/scripts/matrix_testing/NewDatabaseForRule.ps1 b/scripts/matrix_testing/NewDatabaseForRule.ps1 index f9c98f8edb..6dfd6fa86d 100644 --- a/scripts/matrix_testing/NewDatabaseForRule.ps1 +++ b/scripts/matrix_testing/NewDatabaseForRule.ps1 @@ -1,34 +1,39 @@ -. "$PSScriptRoot\GetCompilerExecutable.ps1" -. "$PSScriptRoot\GetCompilerArgs.ps1" +. "$PSScriptRoot\Get-CompilerExecutable.ps1" +. "$PSScriptRoot\Get-CompilerArgs.ps1" . "$PSScriptRoot\GetNewDBName.ps1" function New-Database-For-Rule { param([Parameter(Mandatory)] - [string] - $RuleName, - [Parameter(Mandatory)] - [string] - $RuleTestDir, - [Parameter(Mandatory)] - [string] - $Configuration + [string] + $RuleName, + [Parameter(Mandatory)] + [string] + $RuleTestDir, + [Parameter(Mandatory)] + [string] + $Configuration, + [Parameter(Mandatory)] + [ValidateSet('c', 'cpp')] + [string] + $Language ) Write-Host "Creating Database for Rule $RuleName..." - $cppFiles = Get-ChildItem $RuleTestDir/*.cpp + $cppFiles = Get-ChildItem $RuleTestDir/*.c* $cppFilesString = ([String]::Join(' ', $cppFiles)) Write-Host "Found '.cpp' files $cppFilesString." - $CompilerExecutable = Get-CompilerExecutable -Configuration $Configuration - $CompilerArgs = Get-CompilerArgs -Configuration $Configuration + $CompilerExecutable = Get-CompilerExecutable -Configuration $Configuration -Language $Language + $CompilerArgs = Get-CompilerArgs -Configuration $Configuration -Language $Language - $BUILD_COMMAND="$CompilerExecutable $CompilerArgs $cppFilesString" + $BUILD_COMMAND = "$CompilerExecutable $CompilerArgs $cppFilesString" - if($UseTmpDir){ + if ($UseTmpDir) { $DB_PATH = Get-New-DB-Name - }else{ + } + else { $DB_PATH = Get-New-DB-Name -Dir $RuleTestDir } @@ -36,7 +41,7 @@ function New-Database-For-Rule { $procDetails = Start-Process -FilePath "codeql" -PassThru -NoNewWindow -Wait -ArgumentList "database create -l cpp -s $RuleTestDir --command=`"$BUILD_COMMAND`" $DB_PATH" - if (-Not $procDetails.ExitCode -eq 0){ + if (-Not $procDetails.ExitCode -eq 0) { throw "Database creation failed." } diff --git a/scripts/release/create_draft_release.sh b/scripts/release/create_draft_release.sh index e157a6e732..449f8bc11a 100755 --- a/scripts/release/create_draft_release.sh +++ b/scripts/release/create_draft_release.sh @@ -7,7 +7,6 @@ set -o nounset BRANCH="$1" VERSION="$2" -PREVIOUS_VERSION="$3" if [[ ! $BRANCH == rc/* ]]; then echo "$BRANCH is not an rc branch of the form rc/" @@ -19,8 +18,6 @@ if [ -z "$VERSION" ]; then echo "Version not set explicitly; auto-detecting $VERSION." fi -echo "Using Previous Version: $PREVIOUS_VERSION" - COMMIT_SHA="$(git rev-parse $BRANCH)" echo "Creating draft release for $VERSION from $BRANCH at commit $COMMIT_SHA." @@ -37,36 +34,24 @@ TEMP_DIR="$(mktemp -d)" echo "Identified code-scanning-pack-gen.yml run id: $CODE_SCANNING_PACK_GEN_RUN_ID" -echo "Fetching anonymized Code Scanning pack" -CODE_SCANNING_ANON_ARTIFACT_NAME="code-scanning-cpp-query-pack-anon.zip" -CODE_SCANNING_ANON_VERSIONED_ARTIFACT_NAME="code-scanning-cpp-query-pack-anon-$VERSION.zip" -gh run download $CODE_SCANNING_PACK_GEN_RUN_ID -n "$CODE_SCANNING_ANON_ARTIFACT_NAME" -mv "$CODE_SCANNING_ANON_ARTIFACT_NAME" "$TEMP_DIR/$CODE_SCANNING_ANON_VERSIONED_ARTIFACT_NAME" - echo "Fetching Code Scanning pack" -CODE_SCANNING_ARTIFACT_NAME="code-scanning-cpp-query-pack.zip" -CODE_SCANNING_VERSIONED_ARTIFACT_NAME="code-scanning-cpp-query-pack-$VERSION.zip" +CODE_SCANNING_ARTIFACT_NAME="code-scanning-cpp-query-pack-anon.zip" +CODE_SCANNING_VERSIONED_ARTIFACT_NAME="code-scanning-cpp-query-pack-anon-$VERSION.zip" gh run download $CODE_SCANNING_PACK_GEN_RUN_ID -n "$CODE_SCANNING_ARTIFACT_NAME" mv "$CODE_SCANNING_ARTIFACT_NAME" "$TEMP_DIR/$CODE_SCANNING_VERSIONED_ARTIFACT_NAME" -echo "Fetching anonymized LGTM pack" -LGTM_ANON_ARTIFACT_NAME="lgtm-cpp-query-pack-anon.zip" -LGTM_ANON_VERSIONED_ARTIFACT_NAME="lgtm-cpp-query-pack-anon-$VERSION.zip" -gh run download $CODE_SCANNING_PACK_GEN_RUN_ID -n "$LGTM_ANON_ARTIFACT_NAME" -mv "$LGTM_ANON_ARTIFACT_NAME" "$TEMP_DIR/$LGTM_ANON_VERSIONED_ARTIFACT_NAME" - echo "Fetching LGTM pack" -LGTM_ARTIFACT_NAME="lgtm-cpp-query-pack.zip" -LGTM_VERSIONED_ARTIFACT_NAME="lgtm-cpp-query-pack-$VERSION.zip" +LGTM_ARTIFACT_NAME="lgtm-cpp-query-pack-anon.zip" +LGTM_VERSIONED_ARTIFACT_NAME="lgtm-cpp-query-pack-anon-v$VERSION.zip" gh run download $CODE_SCANNING_PACK_GEN_RUN_ID -n "$LGTM_ARTIFACT_NAME" mv "$LGTM_ARTIFACT_NAME" "$TEMP_DIR/$LGTM_VERSIONED_ARTIFACT_NAME" echo "Generating release notes." -python3 scripts/release/generate_release_notes.py $PREVIOUS_VERSION > "$TEMP_DIR/release_notes_$VERSION.md" +python3 scripts/release/generate_release_notes.py > "$TEMP_DIR/release_notes_$VERSION.md" python3 scripts/release/create_supported_rules_list.py > "$TEMP_DIR/supported_rules_list_$VERSION.md" python3 scripts/release/create_supported_rules_list.py --csv > "$TEMP_DIR/supported_rules_list_$VERSION.csv" -gh release create "$VERSION" -d --target "$BRANCH" -F "$TEMP_DIR/release_notes_$VERSION.md" -t "$VERSION" "$TEMP_DIR/$LGTM_VERSIONED_ARTIFACT_NAME" "$TEMP_DIR/$CODE_SCANNING_VERSIONED_ARTIFACT_NAME" "$TEMP_DIR/$LGTM_ANON_VERSIONED_ARTIFACT_NAME" "$TEMP_DIR/$CODE_SCANNING_ANON_VERSIONED_ARTIFACT_NAME" "$TEMP_DIR/supported_rules_list_$VERSION.md" "$TEMP_DIR/supported_rules_list_$VERSION.csv" docs/user_manual.md +gh release create "v$VERSION" -d --target "$BRANCH" -F "$TEMP_DIR/release_notes_$VERSION.md" -t "v$VERSION" "$TEMP_DIR/$LGTM_VERSIONED_ARTIFACT_NAME" "$TEMP_DIR/$CODE_SCANNING_VERSIONED_ARTIFACT_NAME" "$TEMP_DIR/supported_rules_list_$VERSION.md" "$TEMP_DIR/supported_rules_list_$VERSION.csv" docs/user_manual.md curl \ -X POST \ diff --git a/scripts/release/create_supported_rules_list.py b/scripts/release/create_supported_rules_list.py index 976e5c7497..15a8b5d6b7 100644 --- a/scripts/release/create_supported_rules_list.py +++ b/scripts/release/create_supported_rules_list.py @@ -29,25 +29,26 @@ is_csv = len(sys.argv) == 2 and sys.argv[1] == "--csv" repo_root = Path(__file__).parent.parent.parent -rule_packages_file_path = repo_root.joinpath('rule_packages') -rules_covered = {"AUTOSAR": {}, "CERT-C++": {}} +rules_covered = {"AUTOSAR" : {}, "CERT-C++" : {}, "MISRA-C-2012" : {}, "CERT-C" : {}} # Iterate over rule packages -for rule_package_file_name in os.listdir(rule_packages_file_path): - try: - rule_package_file = open(rule_packages_file_path.joinpath(rule_package_file_name), "r") - except PermissionError: - print("Error: No permission to read the rule package file located at '" + str(rule_package_file_name) + "'") - sys.exit(1) - else: - with rule_package_file: - package_definition = json.load(rule_package_file) - for standard_name, rules in package_definition.items(): - for rule_id, rule_details in rules.items(): - # If we have at least one query specified - if len(rule_details["queries"]) > 0: - rules_covered[standard_name][rule_id] = get_query_short_names(rule_details) +for language_name in ["cpp", "c"]: + rule_packages_file_path = repo_root.joinpath('rule_packages', language_name) + for rule_package_file_name in os.listdir(rule_packages_file_path): + try: + rule_package_file = open(rule_packages_file_path.joinpath(rule_package_file_name), "r") + except PermissionError: + print("Error: No permission to read the rule package file located at '" + str(rule_package_file_name) + "'") + sys.exit(1) + else: + with rule_package_file: + package_definition = json.load(rule_package_file) + for standard_name, rules in package_definition.items(): + for rule_id, rule_details in rules.items(): + # If we have at least one query specified + if len(rule_details["queries"]) > 0: + rules_covered[standard_name][rule_id] = get_query_short_names(rule_details) if is_csv: diff --git a/scripts/release/generate_release_notes.py b/scripts/release/generate_release_notes.py index 063b2f0af8..c6cea8d19f 100644 --- a/scripts/release/generate_release_notes.py +++ b/scripts/release/generate_release_notes.py @@ -41,6 +41,18 @@ print("Usage: " + sys.argv[0] + " [previous-release-tag]", file=sys.stderr) sys.exit(1) + +def transform_legacy_rule_path(p): + """ + We need to account for these files which have been moved since CPP coding + standards. Essentially if there is no language stem it is by default a cpp + file, which should be found in the cpp directory. + """ + if not (p.startswith("rule_packages/c") or p.startswith("rule_packages/cpp")): + return p.replace("rule_packages/", "rule_packages/cpp/") + else: + return p + # Initialise codeql-coding-standards repository object repo_root = Path(__file__).parent.parent.parent repo = Repo(repo_root) @@ -67,7 +79,7 @@ diff_from_last_release = latest_release_commit.diff(head_commit) # Store a mapping from standard -> rules with new queries -> new queries for those rules -new_rules = {"AUTOSAR" : {}, "CERT-C++" : {}} +new_rules = {"AUTOSAR" : {}, "CERT-C++" : {}, "MISRA-C-2012" : {}, "CERT-C" : {}} # Store the text of the newly added change notes change_notes = [] # Store the names of the rule packages with new queries @@ -84,7 +96,7 @@ print("Error: No permission to read the rule package file located at '" + str(added_file) + "'") sys.exit(1) else: - new_rule_packages.append(added_file[len("rule_packages/"):(-len(".json"))]) + new_rule_packages.append(Path(added_file).stem) with rule_package_file: package_definition = json.load(rule_package_file) for standard_name, rules in package_definition.items(): @@ -106,12 +118,13 @@ # Iterate through changed files for diff_changed in diff_from_last_release.iter_change_type('M'): changed_file = diff_changed.a_path + # Identify rule packages which have changed if changed_file.startswith("rule_packages/"): try: - rule_package_file = open(changed_file, "r") + rule_package_file = open(transform_legacy_rule_path(changed_file), "r") except PermissionError: - print("Error: No permission to read the rule package file located at '" + str(rule_package_file_path) + "'") + print("Error: No permission to read the rule package file located at '" + str(changed_file) + "'") sys.exit(1) else: # This rule package is modified, so read in the rule package description as it was in the previous tag @@ -140,7 +153,7 @@ new_query_added = True if new_query_added: # Add this rule package to the list if a new query was added for it - new_rule_packages.append(changed_file[len("rule_packages/"):(-len(".json"))]) + new_rule_packages.append(Path(changed_file).stem) # Determine our supported environments supported_environments = [] diff --git a/scripts/reports/utils.py b/scripts/reports/utils.py index 3bef5b9b00..4fae73d564 100644 --- a/scripts/reports/utils.py +++ b/scripts/reports/utils.py @@ -73,10 +73,13 @@ def __init__(self, sarif_results_file_path): sys.exit(1) extensions = tool["extensions"] + self.coding_standard_relevant_packs = [] + coding_standard_name_endings = ["cpp-coding-standards", "c-coding-standards", "codeql/cpp-all"] for extension in extensions: - if extension["name"].endswith("cpp-coding-standards") or extension["name"] == "codeql/cpp-all": - self.coding_standard_relevant_packs.append(extension) + for ending in coding_standard_name_endings: + if extension["name"].endswith(ending): + self.coding_standard_relevant_packs.append(extension) # Count the results per SARIF rule ID sarif_rule_result_count = defaultdict(int) diff --git a/scripts/verify_rule_package_consistency.py b/scripts/verify_rule_package_consistency.py index 5a89aa5d66..b48b7e83b0 100644 --- a/scripts/verify_rule_package_consistency.py +++ b/scripts/verify_rule_package_consistency.py @@ -15,13 +15,14 @@ print(help_statement.format(script_name=sys.argv[0])) sys.exit(0) -if len(sys.argv) > 1: +if not len(sys.argv) == 2: print("Error: incorrect number of arguments", file=sys.stderr) print("Usage: " + sys.argv[0] + " [--help]", file=sys.stderr) sys.exit(1) repo_root = Path(__file__).parent.parent.parent rules_file_path = repo_root.joinpath('rules.csv') +language_name = sys.argv[1] failed = False @@ -38,16 +39,22 @@ # Skip header row next(rules_reader, None) for rule in rules_reader: - standard = rule[0] - rule_id = rule[1] - queryable = rule[2] - obligation_level = rule[3] - enforcement_level = rule[4] - allocated_targets = rule[5] - rule_title = rule[6] - similar_query = rule[7] - package = rule[8] - difficulty = rule[9] + language = rule[0] + + # only validate rules for the specified language + if not language == language_name: + continue + + standard = rule[1] + rule_id = rule[2] + queryable = rule[3] + obligation_level = rule[4] + enforcement_level = rule[5] + allocated_targets = rule[6] + rule_title = rule[7] + similar_query = rule[8] + package = rule[9] + difficulty = rule[10] # If the rule is associated with a package if package: if not queryable == "Yes": @@ -60,12 +67,12 @@ print(f"Found {count} implementable rules, verifying.") -rule_packages_file_path = repo_root.joinpath('rule_packages') +rule_packages_file_path = repo_root.joinpath('rule_packages', language_name) # Iterate over rule packages, verifying the contents for rule_package_file_name in os.listdir(rule_packages_file_path): try: - rule_package_file = open(rule_packages_file_path.joinpath(rule_package_file_name), "r") + rule_package_file = open(rule_packages_file_path.joinpath(rule_package_file_name), "r") except PermissionError: print("Error: No permission to read the rule package file located at '" + str(rule_package_file_name) + "'") sys.exit(1) @@ -79,7 +86,8 @@ package_json_rule_ids.add(rule_id) standard_short_name = standard_name.split("-")[0].lower() - standard_dir = repo_root.joinpath("cpp").joinpath(standard_short_name) + standard_dir = repo_root.joinpath(language_name).joinpath(standard_short_name) + # Identify the source pack for this standard src_pack_dir = standard_dir.joinpath("src") # Identify the rule src dir @@ -93,12 +101,12 @@ f" - ERROR: Rule {rule_id} included in {package_name}.json but not marked as queryable in rules.csv.") failed = True rules_csv_rule_ids = package_rules_from_csv[package_name] + json_missing_rules = rules_csv_rule_ids.difference(package_json_rule_ids) if json_missing_rules: print( f" - ERROR: Package file {package_name}.json is missing rule records for the following rules: { json_missing_rules }.") failed = True - if failed: print("ERROR: Consistency issues found") sys.exit(1) diff --git a/supported_codeql_configs.json b/supported_codeql_configs.json index b380803460..1fca65f5ac 100644 --- a/supported_codeql_configs.json +++ b/supported_codeql_configs.json @@ -1,9 +1,17 @@ { "supported_environment": [ { - "codeql_cli": "2.7.6", - "codeql_standard_library": "codeql-cli/v2.7.6", - "codeql_cli_bundle": "codeql-bundle-20220120" + "codeql_cli": "2.6.3", + "codeql_standard_library": "codeql-cli/v2.6.3", + "codeql_cli_bundle": "codeql-bundle-20211005" + } + ], + "supported_language" : [ + { + "language" : "cpp" + }, + { + "language" : "c" } ] } \ No newline at end of file
    Subclause 21.4.5, " - basic_string + + basic_string + Element Access"
    ...
    ... only allows inline content elements. if node.name == 'td' and node.pre: node.pre.name = 'code' - # Replace ...... only allows inline content elements. - if node.name == 'td' and node.sample: - node.sample.attrs = {} - node.sample.name = 'code' # Replace
      ...
    - ..., ...