-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Moved fuzzing source into pyvex * Added CI-Fuzz * Attempt to resolve syntax error in cifuzz * Force workflow * Set language to python in cifuzz * Added a more intelligent catch for value error exceptions * Resolved inaccurate crashes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Appeasing the linter a bit * Resolved another pylint complaint * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Moved atheris requirement to testing in setup.cfg * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * The CI server only has Apple Clang and you can't use atheris on Windows, so make it an optional install * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Moved build-script into pyvex source * Updated CIFuzz job with a more specific name and to run on pushes to main * Updated submodule to reflect master --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
b822251
commit d9e3ab6
Showing
5 changed files
with
235 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: OSS-Fuzz | ||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
permissions: {} | ||
jobs: | ||
Fuzzing: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
security-events: write | ||
steps: | ||
- name: Build Fuzzers | ||
id: build | ||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master | ||
with: | ||
oss-fuzz-project-name: 'pyvex' | ||
language: python | ||
- name: Run Fuzzers | ||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master | ||
with: | ||
oss-fuzz-project-name: 'pyvex' | ||
language: python | ||
fuzz-seconds: 600 | ||
output-sarif: true | ||
- name: Upload Crash | ||
uses: actions/upload-artifact@v3 | ||
if: failure() && steps.build.outcome == 'success' | ||
with: | ||
name: artifacts | ||
path: ./out/artifacts | ||
- name: Upload Sarif | ||
if: always() && steps.build.outcome == 'success' | ||
uses: github/codeql-action/upload-sarif@v2 | ||
with: | ||
# Path to SARIF file relative to the root of the repository | ||
sarif_file: cifuzz-sarif/results.sarif | ||
checkout_path: cifuzz-sarif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
#!/bin/bash -eu | ||
# Copyright 2023 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
################################################################################ | ||
|
||
# Since pyvex requires a specific developer build of archinfo, install it from source | ||
cd "$SRC"/archinfo | ||
pip3 install . | ||
|
||
cd "$SRC"/pyvex | ||
pip3 install .[testing] | ||
|
||
# Generate a simple binary for the corpus | ||
echo -ne "start:\n\txor %edi, %edi\nmov \$60, %eax\nsyscall" > /tmp/corpus.s | ||
clang -Os -s /tmp/corpus.s -nostdlib -nostartfiles -m32 -o corpus | ||
zip -r "$OUT"/irsb_fuzzer_seed_corpus.zip corpus | ||
|
||
# Build fuzzers in $OUT | ||
for fuzzer in $(find $SRC -name 'fuzzing/*_fuzzer.py'); do | ||
compile_python_fuzzer "$fuzzer" --add-binary="pyvex/lib/libpyvex.so:pyvex/lib" | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Copyright 2021 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
################################################################################ | ||
""" | ||
Defines the EnhancedFuzzedDataProvider | ||
""" | ||
from atheris import FuzzedDataProvider | ||
|
||
|
||
class EnhancedFuzzedDataProvider(FuzzedDataProvider): | ||
""" | ||
Extends the functionality of FuzzedDataProvider | ||
""" | ||
|
||
def _consume_random_count(self) -> int: | ||
""" | ||
:return: A count of bytes that is strictly in range 0<=n<=remaining_bytes | ||
""" | ||
return self.ConsumeIntInRange(0, self.remaining_bytes()) | ||
|
||
def ConsumeRandomBytes(self) -> bytes: | ||
""" | ||
Consume a 'random' count of the remaining bytes | ||
:return: 0<=n<=remaining_bytes bytes | ||
""" | ||
return self.ConsumeBytes(self._consume_random_count()) | ||
|
||
def ConsumeRemainingBytes(self) -> bytes: | ||
""" | ||
:return: The remaining buffer | ||
""" | ||
return self.ConsumeBytes(self.remaining_bytes()) | ||
|
||
def ConsumeRandomString(self) -> str: | ||
""" | ||
Consume a 'random' length string, excluding surrogates | ||
:return: The string | ||
""" | ||
return self.ConsumeUnicodeNoSurrogates(self._consume_random_count()) | ||
|
||
def ConsumeRemainingString(self) -> str: | ||
""" | ||
:return: The remaining buffer, as a string without surrogates | ||
""" | ||
return self.ConsumeUnicodeNoSurrogates(self.remaining_bytes()) | ||
|
||
def PickValueInEnum(self, enum): | ||
return self.PickValueInList([e.value for e in enum]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
#!/usr/bin/python3 | ||
# Copyright 2023 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
################################################################################ | ||
import re | ||
import sys | ||
from contextlib import contextmanager | ||
from enum import IntEnum | ||
from io import StringIO | ||
|
||
import atheris | ||
|
||
with atheris.instrument_imports(include=["pyvex"]): | ||
import pyvex | ||
|
||
# Additional imports | ||
import archinfo | ||
from enhanced_fdp import EnhancedFuzzedDataProvider | ||
|
||
register_error_msg = re.compile("Register .*? does not exist!") | ||
|
||
|
||
@contextmanager | ||
def nostdout(): | ||
saved_stdout = sys.stdout | ||
saved_stderr = sys.stderr | ||
sys.stdout = StringIO() | ||
sys.stderr = StringIO() | ||
yield | ||
sys.stdout = saved_stdout | ||
sys.stderr = saved_stderr | ||
|
||
|
||
# Save all available architectures off | ||
available_archs = [tup[3]() for tup in archinfo.arch.arch_id_map if len(tup) >= 3] | ||
|
||
|
||
class SupportedOptLevels(IntEnum): | ||
""" | ||
Enumerates the supported optimization levels within pyvex, as derived from the documentation | ||
""" | ||
|
||
StrictUnopt = -1 | ||
Unopt = 0 | ||
Opt = 1 | ||
StrictOpt = 2 | ||
|
||
|
||
def consume_random_arch(fdp: atheris.FuzzedDataProvider) -> archinfo.Arch: | ||
return fdp.PickValueInList(available_archs) | ||
|
||
|
||
def TestOneInput(data: bytes): | ||
fdp = EnhancedFuzzedDataProvider(data) | ||
|
||
arch = consume_random_arch(fdp) | ||
|
||
try: | ||
with nostdout(): | ||
data = fdp.ConsumeRandomBytes() | ||
max_bytes = fdp.ConsumeIntInRange(0, len(data)) | ||
irsb = pyvex.lift( | ||
data, | ||
fdp.ConsumeInt(arch.bits), | ||
arch, | ||
max_bytes=fdp.ConsumeIntInRange(0, len(data)), | ||
max_inst=fdp.ConsumeInt(16), | ||
bytes_offset=fdp.ConsumeIntInRange(0, max_bytes), | ||
opt_level=fdp.PickValueInEnum(SupportedOptLevels), | ||
) | ||
irsb.pp() | ||
return 0 | ||
except pyvex.PyVEXError: | ||
return -1 | ||
except ValueError as e: | ||
if re.match(register_error_msg, str(e)): | ||
return -1 | ||
raise e | ||
except OverflowError: | ||
return -1 | ||
|
||
|
||
def main(): | ||
atheris.Setup(sys.argv, TestOneInput) | ||
atheris.Fuzz() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters