aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp16
-rw-r--r--CHANGELOG.md40
-rw-r--r--Cargo.toml10
-rw-r--r--Cargo.toml.orig14
-rw-r--r--LICENSE-APACHE201
-rw-r--r--LICENSE-MIT25
-rw-r--r--METADATA8
-rw-r--r--README.md2
-rw-r--r--cargo2android.json11
-rwxr-xr-xci/script.sh19
-rw-r--r--libfuzzer/FuzzerBuiltins.h1
-rw-r--r--libfuzzer/FuzzerBuiltinsMsvc.h6
-rw-r--r--libfuzzer/FuzzerCorpus.h38
-rw-r--r--libfuzzer/FuzzerDataFlowTrace.cpp4
-rw-r--r--libfuzzer/FuzzerDataFlowTrace.h14
-rw-r--r--libfuzzer/FuzzerDictionary.h8
-rw-r--r--libfuzzer/FuzzerDriver.cpp12
-rw-r--r--libfuzzer/FuzzerFork.cpp11
-rw-r--r--libfuzzer/FuzzerIO.cpp11
-rw-r--r--libfuzzer/FuzzerIO.h5
-rw-r--r--libfuzzer/FuzzerLoop.cpp30
-rw-r--r--libfuzzer/FuzzerMerge.cpp8
-rw-r--r--libfuzzer/FuzzerMutate.cpp48
-rw-r--r--libfuzzer/FuzzerRandom.h23
-rw-r--r--libfuzzer/FuzzerSHA1.cpp9
-rw-r--r--libfuzzer/FuzzerTracePC.cpp11
-rw-r--r--libfuzzer/FuzzerTracePC.h39
-rw-r--r--libfuzzer/FuzzerUtil.cpp9
-rw-r--r--libfuzzer/FuzzerUtil.h6
-rw-r--r--libfuzzer/FuzzerUtilFuchsia.cpp2
-rw-r--r--libfuzzer/FuzzerUtilPosix.cpp11
-rw-r--r--libfuzzer/tests/FuzzedDataProviderUnittest.cpp14
-rw-r--r--libfuzzer/tests/FuzzerUnittest.cpp314
-rw-r--r--patches/Android.bp.patch25
-rw-r--r--src/lib.rs264
36 files changed, 277 insertions, 994 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 4d6cfd1..600bdb7 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "a89115ac1105fa0c7c7d9cb5cdb479af36031aff"
+ "sha1": "4b33ad40af65972c122a16180f51278830dff0a5"
}
}
diff --git a/Android.bp b/Android.bp
index fbfcb90..65d3b7a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,4 +1,4 @@
-// This file is generated by cargo2android.py --config cargo2android.json.
+// This file is generated by cargo2android.py --run --dependencies --device --features arbitrary-derive --patch patches/Android.bp.patch.
// Do not modify this file as changes will be overridden on upgrade.
package {
@@ -38,13 +38,19 @@ rust_library_rlib {
name: "liblibfuzzer_sys",
host_supported: true,
crate_name: "libfuzzer_sys",
- cargo_env_compat: true,
- cargo_pkg_version: "0.4.2",
srcs: ["src/lib.rs"],
edition: "2018",
features: ["arbitrary-derive"],
- rustlibs: [
+ rlibs: [
"libarbitrary",
- "libonce_cell",
],
}
+
+// dependent_library ["feature_list"]
+// arbitrary-1.0.0 "derive,derive_arbitrary"
+// cc-1.0.67
+// derive_arbitrary-1.0.0
+// proc-macro2-1.0.26 "default,proc-macro"
+// quote-1.0.9 "default,proc-macro"
+// syn-1.0.68 "clone-impls,default,derive,parsing,printing,proc-macro,quote"
+// unicode-xid-0.2.1 "default"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 77be1fd..26345b2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,46 +28,6 @@ Released YYYY-MM-DD.
--------------------------------------------------------------------------------
-## 0.4.2
-
-Released 2020-05-26.
-
-### Changed
-
-* Improved performance of checking for whether `cargo fuzz` is requesting the
- `std::fmt::Debug` output of an input or not. This is always false during
- regular fuzzing, so making this check faster should give slightly better
- fuzzing throughput.
-
---------------------------------------------------------------------------------
-
-## 0.4.1
-
-Released 2020-05-13.
-
-### Added
-
-* Added support for defining custom mutators. See [the documentation for the
- `fuzz_mutator!`
- macro](https://docs.rs/libfuzzer-sys/0.4.1/libfuzzer_sys/macro.fuzz_mutator.html)
- for details.
-
-### Changed
-
-* Upgraded libfuzzer to llvm/llvm-project's 70cbc6d.
-
---------------------------------------------------------------------------------
-
-## 0.4.0
-
-Released 2021-02-24.
-
-### Changed
-
-* The public `arbitrary` dependency was updated to version 1.0.
-
---------------------------------------------------------------------------------
-
## 0.3.5
Released 2020-11-18.
diff --git a/Cargo.toml b/Cargo.toml
index 4be2136..a1635d7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "libfuzzer-sys"
-version = "0.4.2"
+version = "0.4.0"
authors = ["The rust-fuzz Project Developers"]
description = "A wrapper around LLVM's libFuzzer runtime."
readme = "./README.md"
@@ -21,14 +21,6 @@ license = "MIT/Apache-2.0/NCSA"
repository = "https://github.com/rust-fuzz/libfuzzer"
[dependencies.arbitrary]
version = "1"
-
-[dependencies.once_cell]
-version = "1"
-[dev-dependencies.flate2]
-version = "1.0.20"
-
-[dev-dependencies.rand]
-version = "0.8.3"
[build-dependencies.cc]
version = "1.0"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 72285b9..db1d7b3 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -6,25 +6,13 @@ license = "MIT/Apache-2.0/NCSA"
name = "libfuzzer-sys"
readme = "./README.md"
repository = "https://github.com/rust-fuzz/libfuzzer"
-version = "0.4.2"
+version = "0.4.0"
[dependencies]
arbitrary = "1"
-once_cell = "1"
[build-dependencies]
cc = "1.0"
[features]
arbitrary-derive = ["arbitrary/derive"]
-
-[workspace]
-members = [
- "./example",
- "./example_arbitrary",
- "./example_mutator",
-]
-
-[dev-dependencies]
-flate2 = "1.0.20"
-rand = "0.8.3"
diff --git a/LICENSE-APACHE b/LICENSE-APACHE
deleted file mode 100644
index 16fe87b..0000000
--- a/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-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.
diff --git a/LICENSE-MIT b/LICENSE-MIT
deleted file mode 100644
index 25597d5..0000000
--- a/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2010 The Rust Project Developers
-
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
diff --git a/METADATA b/METADATA
index abca0eb..bcae820 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/libfuzzer-sys/libfuzzer-sys-0.4.2.crate"
+ value: "https://static.crates.io/crates/libfuzzer-sys/libfuzzer-sys-0.4.0.crate"
}
- version: "0.4.2"
+ version: "0.4.0"
license_type: NOTICE
last_upgrade_date {
year: 2021
- month: 6
- day: 21
+ month: 4
+ day: 1
}
}
diff --git a/README.md b/README.md
index 8bdba6e..1d01871 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Then add a dependency on the `fuzzer-sys` crate and your own crate:
```toml
[dependencies]
-libfuzzer-sys = "0.4.0"
+libfuzzer-sys = "0.3.0"
your_crate = { path = "../path/to/your/crate" }
```
diff --git a/cargo2android.json b/cargo2android.json
deleted file mode 100644
index 01e723e..0000000
--- a/cargo2android.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "dependencies": true,
- "device": true,
- "features": "arbitrary-derive",
- "force-rlib": true,
- "lib-blocklist": [
- "fuzzer",
- "stdc++"
- ],
- "run": true
-} \ No newline at end of file
diff --git a/ci/script.sh b/ci/script.sh
index 91fad80..25914fd 100755
--- a/ci/script.sh
+++ b/ci/script.sh
@@ -5,8 +5,6 @@ cd $(dirname $0)/..
export CARGO_TARGET_DIR=$(pwd)/target
-cargo test --doc
-
pushd ./example
cargo rustc \
--release \
@@ -41,20 +39,3 @@ RUST_LIBFUZZER_DEBUG_PATH=$(pwd)/debug_output \
cat $(pwd)/debug_output
grep -q Rgb $(pwd)/debug_output
popd
-
-pushd ./example_mutator
-cargo rustc \
- --release \
- -- \
- -Cpasses='sancov' \
- -Cllvm-args=-sanitizer-coverage-level=3 \
- -Cllvm-args=-sanitizer-coverage-trace-compares \
- -Cllvm-args=-sanitizer-coverage-inline-8bit-counters \
- -Cllvm-args=-sanitizer-coverage-stack-depth \
- -Cllvm-args=-sanitizer-coverage-trace-geps \
- -Cllvm-args=-sanitizer-coverage-prune-blocks=0 \
- -Zsanitizer=address
-(! $CARGO_TARGET_DIR/release/example_mutator -runs=10000000)
-popd
-
-echo "All good!"
diff --git a/libfuzzer/FuzzerBuiltins.h b/libfuzzer/FuzzerBuiltins.h
index ce0bd5c..4c0ada8 100644
--- a/libfuzzer/FuzzerBuiltins.h
+++ b/libfuzzer/FuzzerBuiltins.h
@@ -26,6 +26,7 @@ inline uint32_t Bswap(uint32_t x) { return __builtin_bswap32(x); }
inline uint64_t Bswap(uint64_t x) { return __builtin_bswap64(x); }
inline uint32_t Clzll(unsigned long long X) { return __builtin_clzll(X); }
+inline uint32_t Clz(unsigned long long X) { return __builtin_clz(X); }
inline int Popcountll(unsigned long long X) { return __builtin_popcountll(X); }
} // namespace fuzzer
diff --git a/libfuzzer/FuzzerBuiltinsMsvc.h b/libfuzzer/FuzzerBuiltinsMsvc.h
index ab191b6..c5bec97 100644
--- a/libfuzzer/FuzzerBuiltinsMsvc.h
+++ b/libfuzzer/FuzzerBuiltinsMsvc.h
@@ -52,6 +52,12 @@ inline uint32_t Clzll(uint64_t X) {
return 64;
}
+inline uint32_t Clz(uint32_t X) {
+ unsigned long LeadZeroIdx = 0;
+ if (_BitScanReverse(&LeadZeroIdx, X)) return 31 - LeadZeroIdx;
+ return 32;
+}
+
inline int Popcountll(unsigned long long X) {
#if !defined(_M_ARM) && !defined(_M_X64)
return __popcnt(X) + __popcnt(X >> 32);
diff --git a/libfuzzer/FuzzerCorpus.h b/libfuzzer/FuzzerCorpus.h
index f8c1260..daea4f5 100644
--- a/libfuzzer/FuzzerCorpus.h
+++ b/libfuzzer/FuzzerCorpus.h
@@ -44,7 +44,7 @@ struct InputInfo {
// Power schedule.
bool NeedsEnergyUpdate = false;
double Energy = 0.0;
- double SumIncidence = 0.0;
+ size_t SumIncidence = 0;
Vector<std::pair<uint32_t, uint16_t>> FeatureFreqs;
// Delete feature Idx and its frequency from FeatureFreqs.
@@ -74,28 +74,27 @@ struct InputInfo {
void UpdateEnergy(size_t GlobalNumberOfFeatures, bool ScalePerExecTime,
std::chrono::microseconds AverageUnitExecutionTime) {
Energy = 0.0;
- SumIncidence = 0.0;
+ SumIncidence = 0;
// Apply add-one smoothing to locally discovered features.
for (auto F : FeatureFreqs) {
- double LocalIncidence = F.second + 1;
- Energy -= LocalIncidence * log(LocalIncidence);
+ size_t LocalIncidence = F.second + 1;
+ Energy -= LocalIncidence * logl(LocalIncidence);
SumIncidence += LocalIncidence;
}
// Apply add-one smoothing to locally undiscovered features.
- // PreciseEnergy -= 0; // since log(1.0) == 0)
- SumIncidence +=
- static_cast<double>(GlobalNumberOfFeatures - FeatureFreqs.size());
+ // PreciseEnergy -= 0; // since logl(1.0) == 0)
+ SumIncidence += (GlobalNumberOfFeatures - FeatureFreqs.size());
// Add a single locally abundant feature apply add-one smoothing.
- double AbdIncidence = static_cast<double>(NumExecutedMutations + 1);
- Energy -= AbdIncidence * log(AbdIncidence);
+ size_t AbdIncidence = NumExecutedMutations + 1;
+ Energy -= AbdIncidence * logl(AbdIncidence);
SumIncidence += AbdIncidence;
// Normalize.
if (SumIncidence != 0)
- Energy = Energy / SumIncidence + log(SumIncidence);
+ Energy = (Energy / SumIncidence) + logl(SumIncidence);
if (ScalePerExecTime) {
// Scaling to favor inputs with lower execution time.
@@ -214,8 +213,6 @@ public:
assert(!U.empty());
if (FeatureDebug)
Printf("ADD_TO_CORPUS %zd NF %zd\n", Inputs.size(), NumFeatures);
- // Inputs.size() is cast to uint32_t below.
- assert(Inputs.size() < std::numeric_limits<uint32_t>::max());
Inputs.push_back(new InputInfo());
InputInfo &II = *Inputs.back();
II.U = U;
@@ -227,7 +224,7 @@ public:
II.HasFocusFunction = HasFocusFunction;
// Assign maximal energy to the new seed.
II.Energy = RareFeatures.empty() ? 1.0 : log(RareFeatures.size());
- II.SumIncidence = static_cast<double>(RareFeatures.size());
+ II.SumIncidence = RareFeatures.size();
II.NeedsEnergyUpdate = false;
std::sort(II.UniqFeatureSet.begin(), II.UniqFeatureSet.end());
ComputeSHA1(U.data(), U.size(), II.Sha1);
@@ -402,7 +399,7 @@ public:
// Zero energy seeds will never be fuzzed and remain zero energy.
if (II->Energy > 0.0) {
II->SumIncidence += 1;
- II->Energy += log(II->SumIncidence) / II->SumIncidence;
+ II->Energy += logl(II->SumIncidence) / II->SumIncidence;
}
}
@@ -429,8 +426,7 @@ public:
NumUpdatedFeatures++;
if (FeatureDebug)
Printf("ADD FEATURE %zd sz %d\n", Idx, NewSize);
- // Inputs.size() is guaranteed to be less than UINT32_MAX by AddToCorpus.
- SmallestElementPerFeature[Idx] = static_cast<uint32_t>(Inputs.size());
+ SmallestElementPerFeature[Idx] = Inputs.size();
InputSizesPerFeature[Idx] = NewSize;
return true;
}
@@ -468,7 +464,7 @@ private:
static const bool FeatureDebug = false;
- uint32_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
+ size_t GetFeature(size_t Idx) const { return InputSizesPerFeature[Idx]; }
void ValidateFeatureSet() {
if (FeatureDebug)
@@ -543,11 +539,9 @@ private:
if (VanillaSchedule) {
for (size_t i = 0; i < N; i++)
- Weights[i] =
- Inputs[i]->NumFeatures
- ? static_cast<double>((i + 1) *
- (Inputs[i]->HasFocusFunction ? 1000 : 1))
- : 0.;
+ Weights[i] = Inputs[i]->NumFeatures
+ ? (i + 1) * (Inputs[i]->HasFocusFunction ? 1000 : 1)
+ : 0.;
}
if (FeatureDebug) {
diff --git a/libfuzzer/FuzzerDataFlowTrace.cpp b/libfuzzer/FuzzerDataFlowTrace.cpp
index 23d4225..0e9cdf7 100644
--- a/libfuzzer/FuzzerDataFlowTrace.cpp
+++ b/libfuzzer/FuzzerDataFlowTrace.cpp
@@ -60,7 +60,6 @@ bool BlockCoverage::AppendCoverage(std::istream &IN) {
CoveredBlocks.push_back(BB);
}
if (CoveredBlocks.empty()) return false;
- // Ensures no CoverageVector is longer than UINT32_MAX.
uint32_t NumBlocks = CoveredBlocks.back();
CoveredBlocks.pop_back();
for (auto BB : CoveredBlocks)
@@ -201,8 +200,7 @@ bool DataFlowTrace::Init(const std::string &DirPath, std::string *FocusFunction,
Printf("INFO: AUTOFOCUS: %zd %s\n", FocusFuncIdx,
FunctionNames[FocusFuncIdx].c_str());
for (size_t i = 0; i < NumFunctions; i++) {
- if (Weights[i] == 0.0)
- continue;
+ if (!Weights[i]) continue;
Printf(" [%zd] W %g\tBB-tot %u\tBB-cov %u\tEntryFreq %u:\t%s\n", i,
Weights[i], Coverage.GetNumberOfBlocks(i),
Coverage.GetNumberOfCoveredBlocks(i), Coverage.GetCounter(i, 0),
diff --git a/libfuzzer/FuzzerDataFlowTrace.h b/libfuzzer/FuzzerDataFlowTrace.h
index 07c03bb..d6e3de3 100644
--- a/libfuzzer/FuzzerDataFlowTrace.h
+++ b/libfuzzer/FuzzerDataFlowTrace.h
@@ -42,8 +42,7 @@ int CollectDataFlow(const std::string &DFTBinary, const std::string &DirPath,
const Vector<SizedFile> &CorporaFiles);
class BlockCoverage {
-public:
- // These functions guarantee no CoverageVector is longer than UINT32_MAX.
+ public:
bool AppendCoverage(std::istream &IN);
bool AppendCoverage(const std::string &S);
@@ -51,8 +50,7 @@ public:
uint32_t GetCounter(size_t FunctionId, size_t BasicBlockId) {
auto It = Functions.find(FunctionId);
- if (It == Functions.end())
- return 0;
+ if (It == Functions.end()) return 0;
const auto &Counters = It->second;
if (BasicBlockId < Counters.size())
return Counters[BasicBlockId];
@@ -63,7 +61,7 @@ public:
auto It = Functions.find(FunctionId);
if (It == Functions.end()) return 0;
const auto &Counters = It->second;
- return static_cast<uint32_t>(Counters.size());
+ return Counters.size();
}
uint32_t GetNumberOfCoveredBlocks(size_t FunctionId) {
@@ -80,7 +78,8 @@ public:
Vector<double> FunctionWeights(size_t NumFunctions) const;
void clear() { Functions.clear(); }
-private:
+ private:
+
typedef Vector<uint32_t> CoverageVector;
uint32_t NumberOfCoveredBlocks(const CoverageVector &Counters) const {
@@ -92,8 +91,7 @@ private:
}
uint32_t NumberOfUncoveredBlocks(const CoverageVector &Counters) const {
- return static_cast<uint32_t>(Counters.size()) -
- NumberOfCoveredBlocks(Counters);
+ return Counters.size() - NumberOfCoveredBlocks(Counters);
}
uint32_t SmallestNonZeroCounter(const CoverageVector &Counters) const {
diff --git a/libfuzzer/FuzzerDictionary.h b/libfuzzer/FuzzerDictionary.h
index db55907..301c5d9 100644
--- a/libfuzzer/FuzzerDictionary.h
+++ b/libfuzzer/FuzzerDictionary.h
@@ -23,14 +23,12 @@ template <size_t kMaxSizeT> class FixedWord {
public:
static const size_t kMaxSize = kMaxSizeT;
FixedWord() {}
- FixedWord(const uint8_t *B, size_t S) { Set(B, S); }
+ FixedWord(const uint8_t *B, uint8_t S) { Set(B, S); }
- void Set(const uint8_t *B, size_t S) {
- static_assert(kMaxSizeT <= std::numeric_limits<uint8_t>::max(),
- "FixedWord::kMaxSizeT cannot fit in a uint8_t.");
+ void Set(const uint8_t *B, uint8_t S) {
assert(S <= kMaxSize);
memcpy(Data, B, S);
- Size = static_cast<uint8_t>(S);
+ Size = S;
}
bool operator==(const FixedWord<kMaxSize> &w) const {
diff --git a/libfuzzer/FuzzerDriver.cpp b/libfuzzer/FuzzerDriver.cpp
index ceaa907..447cafc 100644
--- a/libfuzzer/FuzzerDriver.cpp
+++ b/libfuzzer/FuzzerDriver.cpp
@@ -159,14 +159,14 @@ static bool ParseOneFlag(const char *Param) {
const char *Str = FlagValue(Param, Name);
if (Str) {
if (FlagDescriptions[F].IntFlag) {
- auto Val = MyStol(Str);
- *FlagDescriptions[F].IntFlag = static_cast<int>(Val);
+ int Val = MyStol(Str);
+ *FlagDescriptions[F].IntFlag = Val;
if (Flags.verbosity >= 2)
Printf("Flag: %s %d\n", Name, Val);
return true;
} else if (FlagDescriptions[F].UIntFlag) {
- auto Val = std::stoul(Str);
- *FlagDescriptions[F].UIntFlag = static_cast<unsigned int>(Val);
+ unsigned int Val = std::stoul(Str);
+ *FlagDescriptions[F].UIntFlag = Val;
if (Flags.verbosity >= 2)
Printf("Flag: %s %u\n", Name, Val);
return true;
@@ -789,8 +789,8 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
unsigned Seed = Flags.seed;
// Initialize Seed.
if (Seed == 0)
- Seed = static_cast<unsigned>(
- std::chrono::system_clock::now().time_since_epoch().count() + GetPid());
+ Seed =
+ std::chrono::system_clock::now().time_since_epoch().count() + GetPid();
if (Flags.verbosity)
Printf("INFO: Seed: %u\n", Seed);
diff --git a/libfuzzer/FuzzerFork.cpp b/libfuzzer/FuzzerFork.cpp
index 5134a5d..84725d2 100644
--- a/libfuzzer/FuzzerFork.cpp
+++ b/libfuzzer/FuzzerFork.cpp
@@ -142,9 +142,7 @@ struct GlobalEnv {
CollectDFT(SF);
}
auto Time2 = std::chrono::system_clock::now();
- auto DftTimeInSeconds = duration_cast<seconds>(Time2 - Time1).count();
- assert(DftTimeInSeconds < std::numeric_limits<int>::max());
- Job->DftTimeInSeconds = static_cast<int>(DftTimeInSeconds);
+ Job->DftTimeInSeconds = duration_cast<seconds>(Time2 - Time1).count();
}
if (!Seeds.empty()) {
Job->SeedListPath =
@@ -316,11 +314,8 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options,
Env.Files.push_back(File.File);
} else {
auto CFPath = DirPlusFile(Env.TempDir, "merge.txt");
- Set<uint32_t> NewFeatures, NewCov;
- CrashResistantMerge(Env.Args, {}, SeedFiles, &Env.Files, Env.Features,
- &NewFeatures, Env.Cov, &NewCov, CFPath, false);
- Env.Features.insert(NewFeatures.begin(), NewFeatures.end());
- Env.Cov.insert(NewFeatures.begin(), NewFeatures.end());
+ CrashResistantMerge(Env.Args, {}, SeedFiles, &Env.Files, {}, &Env.Features,
+ {}, &Env.Cov, CFPath, false);
RemoveFile(CFPath);
}
Printf("INFO: -fork=%d: %zd seed inputs, starting to fuzz in %s\n", NumJobs,
diff --git a/libfuzzer/FuzzerIO.cpp b/libfuzzer/FuzzerIO.cpp
index 7f149ac..54a7219 100644
--- a/libfuzzer/FuzzerIO.cpp
+++ b/libfuzzer/FuzzerIO.cpp
@@ -90,9 +90,8 @@ void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
fclose(Out);
}
-void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V, long *Epoch,
- size_t MaxSize, bool ExitOnError,
- Vector<std::string> *VPaths) {
+void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
+ long *Epoch, size_t MaxSize, bool ExitOnError) {
long E = Epoch ? *Epoch : 0;
Vector<std::string> Files;
ListFilesInDirRecursive(Path, Epoch, &Files, /*TopDir*/true);
@@ -104,14 +103,12 @@ void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V, long *Epoch,
if ((NumLoaded & (NumLoaded - 1)) == 0 && NumLoaded >= 1024)
Printf("Loaded %zd/%zd files from %s\n", NumLoaded, Files.size(), Path);
auto S = FileToVector(X, MaxSize, ExitOnError);
- if (!S.empty()) {
+ if (!S.empty())
V->push_back(S);
- if (VPaths)
- VPaths->push_back(X);
- }
}
}
+
void GetSizedFilesFromDir(const std::string &Dir, Vector<SizedFile> *V) {
Vector<std::string> Files;
ListFilesInDirRecursive(Dir, 0, &Files, /*TopDir*/true);
diff --git a/libfuzzer/FuzzerIO.h b/libfuzzer/FuzzerIO.h
index bde1826..abd2511 100644
--- a/libfuzzer/FuzzerIO.h
+++ b/libfuzzer/FuzzerIO.h
@@ -32,9 +32,8 @@ void WriteToFile(const Unit &U, const std::string &Path);
void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path);
void AppendToFile(const std::string &Data, const std::string &Path);
-void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V, long *Epoch,
- size_t MaxSize, bool ExitOnError,
- Vector<std::string> *VPaths = 0);
+void ReadDirToVectorOfUnits(const char *Path, Vector<Unit> *V,
+ long *Epoch, size_t MaxSize, bool ExitOnError);
// Returns "Dir/FileName" or equivalent for the current OS.
std::string DirPlusFile(const std::string &DirPath,
diff --git a/libfuzzer/FuzzerLoop.cpp b/libfuzzer/FuzzerLoop.cpp
index 86a78ab..6e3bf44 100644
--- a/libfuzzer/FuzzerLoop.cpp
+++ b/libfuzzer/FuzzerLoop.cpp
@@ -414,25 +414,19 @@ void Fuzzer::RereadOutputCorpus(size_t MaxSize) {
if (Options.OutputCorpus.empty() || !Options.ReloadIntervalSec)
return;
Vector<Unit> AdditionalCorpus;
- Vector<std::string> AdditionalCorpusPaths;
- ReadDirToVectorOfUnits(
- Options.OutputCorpus.c_str(), &AdditionalCorpus,
- &EpochOfLastReadOfOutputCorpus, MaxSize,
- /*ExitOnError*/ false,
- (Options.Verbosity >= 2 ? &AdditionalCorpusPaths : nullptr));
+ ReadDirToVectorOfUnits(Options.OutputCorpus.c_str(), &AdditionalCorpus,
+ &EpochOfLastReadOfOutputCorpus, MaxSize,
+ /*ExitOnError*/ false);
if (Options.Verbosity >= 2)
Printf("Reload: read %zd new units.\n", AdditionalCorpus.size());
bool Reloaded = false;
- for (size_t i = 0; i != AdditionalCorpus.size(); ++i) {
- auto &U = AdditionalCorpus[i];
+ for (auto &U : AdditionalCorpus) {
if (U.size() > MaxSize)
U.resize(MaxSize);
if (!Corpus.HasUnit(U)) {
if (RunOne(U.data(), U.size())) {
CheckExitOnSrcPosOrItem();
Reloaded = true;
- if (Options.Verbosity >= 2)
- Printf("Reloaded %s\n", AdditionalCorpusPaths[i].c_str());
}
}
}
@@ -446,9 +440,8 @@ void Fuzzer::PrintPulseAndReportSlowInput(const uint8_t *Data, size_t Size) {
if (!(TotalNumberOfRuns & (TotalNumberOfRuns - 1)) &&
secondsSinceProcessStartUp() >= 2)
PrintStats("pulse ");
- auto Threshhold =
- static_cast<long>(static_cast<double>(TimeOfLongestUnitInSeconds) * 1.1);
- if (TimeOfUnit > Threshhold && TimeOfUnit >= Options.ReportSlowUnits) {
+ if (TimeOfUnit > TimeOfLongestUnitInSeconds * 1.1 &&
+ TimeOfUnit >= Options.ReportSlowUnits) {
TimeOfLongestUnitInSeconds = TimeOfUnit;
Printf("Slowest unit: %zd s:\n", TimeOfLongestUnitInSeconds);
WriteUnitToFileWithPrefix({Data, Data + Size}, "slow-unit-");
@@ -508,8 +501,6 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
bool *FoundUniqFeatures) {
if (!Size)
return false;
- // Largest input length should be INT_MAX.
- assert(Size < std::numeric_limits<uint32_t>::max());
ExecuteCallback(Data, Size);
auto TimeOfUnit = duration_cast<microseconds>(UnitStopTime - UnitStartTime);
@@ -517,8 +508,8 @@ bool Fuzzer::RunOne(const uint8_t *Data, size_t Size, bool MayDeleteFile,
UniqFeatureSetTmp.clear();
size_t FoundUniqFeaturesOfII = 0;
size_t NumUpdatesBefore = Corpus.NumFeatureUpdates();
- TPC.CollectFeatures([&](uint32_t Feature) {
- if (Corpus.AddFeature(Feature, static_cast<uint32_t>(Size), Options.Shrink))
+ TPC.CollectFeatures([&](size_t Feature) {
+ if (Corpus.AddFeature(Feature, Size, Options.Shrink))
UniqFeatureSetTmp.push_back(Feature);
if (Options.Entropic)
Corpus.UpdateFeatureFrequency(II, Feature);
@@ -584,10 +575,7 @@ static bool LooseMemeq(const uint8_t *A, const uint8_t *B, size_t Size) {
!memcmp(A + Size - Limit / 2, B + Size - Limit / 2, Limit / 2);
}
-// This method is not inlined because it would cause a test to fail where it
-// is part of the stack unwinding. See D97975 for details.
-ATTRIBUTE_NOINLINE void Fuzzer::ExecuteCallback(const uint8_t *Data,
- size_t Size) {
+void Fuzzer::ExecuteCallback(const uint8_t *Data, size_t Size) {
TPC.RecordInitialStack();
TotalNumberOfRuns++;
assert(InFuzzingThread());
diff --git a/libfuzzer/FuzzerMerge.cpp b/libfuzzer/FuzzerMerge.cpp
index 162453c..e3ad8b3 100644
--- a/libfuzzer/FuzzerMerge.cpp
+++ b/libfuzzer/FuzzerMerge.cpp
@@ -82,9 +82,9 @@ bool Merger::Parse(std::istream &IS, bool ParseCoverage) {
while (std::getline(IS, Line, '\n')) {
std::istringstream ISS1(Line);
std::string Marker;
- uint32_t N;
- if (!(ISS1 >> Marker) || !(ISS1 >> N))
- return false;
+ size_t N;
+ ISS1 >> Marker;
+ ISS1 >> N;
if (Marker == "STARTED") {
// STARTED FILE_ID FILE_SIZE
if (ExpectedStartMarker != N)
@@ -137,8 +137,6 @@ size_t Merger::Merge(const Set<uint32_t> &InitialFeatures,
const Set<uint32_t> &InitialCov, Set<uint32_t> *NewCov,
Vector<std::string> *NewFiles) {
NewFiles->clear();
- NewFeatures->clear();
- NewCov->clear();
assert(NumFilesInFirstCorpus <= Files.size());
Set<uint32_t> AllFeatures = InitialFeatures;
diff --git a/libfuzzer/FuzzerMutate.cpp b/libfuzzer/FuzzerMutate.cpp
index 4650f1b..cf34a9f 100644
--- a/libfuzzer/FuzzerMutate.cpp
+++ b/libfuzzer/FuzzerMutate.cpp
@@ -61,20 +61,14 @@ MutationDispatcher::MutationDispatcher(Random &Rand,
}
static char RandCh(Random &Rand) {
- if (Rand.RandBool())
- return static_cast<char>(Rand(256));
+ if (Rand.RandBool()) return Rand(256);
const char Special[] = "!*'();:@&=+$,/?%#[]012Az-`~.\xff\x00";
return Special[Rand(sizeof(Special) - 1)];
}
size_t MutationDispatcher::Mutate_Custom(uint8_t *Data, size_t Size,
size_t MaxSize) {
- if (EF->__msan_unpoison)
- EF->__msan_unpoison(Data, Size);
- if (EF->__msan_unpoison_param)
- EF->__msan_unpoison_param(4);
- return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize,
- Rand.Rand<unsigned int>());
+ return EF->LLVMFuzzerCustomMutator(Data, Size, MaxSize, Rand.Rand());
}
size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
@@ -87,18 +81,8 @@ size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
return 0;
CustomCrossOverInPlaceHere.resize(MaxSize);
auto &U = CustomCrossOverInPlaceHere;
-
- if (EF->__msan_unpoison) {
- EF->__msan_unpoison(Data, Size);
- EF->__msan_unpoison(Other.data(), Other.size());
- EF->__msan_unpoison(U.data(), U.size());
- }
- if (EF->__msan_unpoison_param)
- EF->__msan_unpoison_param(7);
size_t NewSize = EF->LLVMFuzzerCustomCrossOver(
- Data, Size, Other.data(), Other.size(), U.data(), U.size(),
- Rand.Rand<unsigned int>());
-
+ Data, Size, Other.data(), Other.size(), U.data(), U.size(), Rand.Rand());
if (!NewSize)
return 0;
assert(NewSize <= MaxSize && "CustomCrossOver returned overisized unit");
@@ -151,8 +135,7 @@ size_t MutationDispatcher::Mutate_InsertRepeatedBytes(uint8_t *Data,
// Insert new values at Data[Idx].
memmove(Data + Idx + N, Data + Idx, Size - Idx);
// Give preference to 0x00 and 0xff.
- uint8_t Byte = static_cast<uint8_t>(
- Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255));
+ uint8_t Byte = Rand.RandBool() ? Rand(256) : (Rand.RandBool() ? 0 : 255);
for (size_t i = 0; i < N; i++)
Data[Idx + i] = Byte;
return Size + N;
@@ -195,8 +178,7 @@ size_t MutationDispatcher::ApplyDictionaryEntry(uint8_t *Data, size_t Size,
Size += W.size();
} else { // Overwrite some bytes with W.
if (W.size() > Size) return 0;
- size_t Idx =
- UsePositionHint ? DE.GetPositionHint() : Rand(Size + 1 - W.size());
+ size_t Idx = UsePositionHint ? DE.GetPositionHint() : Rand(Size - W.size());
memcpy(Data + Idx, W.data(), W.size());
}
return Size;
@@ -245,8 +227,8 @@ DictionaryEntry MutationDispatcher::MakeDictionaryEntryFromCMP(
T Arg1, T Arg2, const uint8_t *Data, size_t Size) {
if (Rand.RandBool()) Arg1 = Bswap(Arg1);
if (Rand.RandBool()) Arg2 = Bswap(Arg2);
- T Arg1Mutation = static_cast<T>(Arg1 + Rand(-1, 1));
- T Arg2Mutation = static_cast<T>(Arg2 + Rand(-1, 1));
+ T Arg1Mutation = Arg1 + Rand(-1, 1);
+ T Arg2Mutation = Arg2 + Rand(-1, 1);
return MakeDictionaryEntryFromCMP(&Arg1, &Arg2, &Arg1Mutation, &Arg2Mutation,
sizeof(Arg1), Data, Size);
}
@@ -263,23 +245,23 @@ size_t MutationDispatcher::Mutate_AddWordFromTORC(
DictionaryEntry DE;
switch (Rand(4)) {
case 0: {
- auto X = TPC.TORC8.Get(Rand.Rand<size_t>());
+ auto X = TPC.TORC8.Get(Rand.Rand());
DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
} break;
case 1: {
- auto X = TPC.TORC4.Get(Rand.Rand<size_t>());
+ auto X = TPC.TORC4.Get(Rand.Rand());
if ((X.A >> 16) == 0 && (X.B >> 16) == 0 && Rand.RandBool())
DE = MakeDictionaryEntryFromCMP((uint16_t)X.A, (uint16_t)X.B, Data, Size);
else
DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
} break;
case 2: {
- auto X = TPC.TORCW.Get(Rand.Rand<size_t>());
+ auto X = TPC.TORCW.Get(Rand.Rand());
DE = MakeDictionaryEntryFromCMP(X.A, X.B, Data, Size);
} break;
case 3: if (Options.UseMemmem) {
- auto X = TPC.MMT.Get(Rand.Rand<size_t>());
- DE = DictionaryEntry(X);
+ auto X = TPC.MMT.Get(Rand.Rand());
+ DE = DictionaryEntry(X);
} break;
default:
assert(0);
@@ -405,12 +387,12 @@ size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
assert(Off + sizeof(T) <= Size);
T Val;
if (Off < 64 && !Rand(4)) {
- Val = static_cast<T>(Size);
+ Val = Size;
if (Rand.RandBool())
Val = Bswap(Val);
} else {
memcpy(&Val, Data + Off, sizeof(Val));
- T Add = static_cast<T>(Rand(21));
+ T Add = Rand(21);
Add -= 10;
if (Rand.RandBool())
Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
@@ -480,7 +462,7 @@ void MutationDispatcher::RecordSuccessfulMutationSequence() {
assert(DE->GetW().size());
// Linear search is fine here as this happens seldom.
if (!PersistentAutoDictionary.ContainsWord(DE->GetW()))
- PersistentAutoDictionary.push_back(*DE);
+ PersistentAutoDictionary.push_back({DE->GetW(), 1});
}
}
diff --git a/libfuzzer/FuzzerRandom.h b/libfuzzer/FuzzerRandom.h
index ad6c07e..659283e 100644
--- a/libfuzzer/FuzzerRandom.h
+++ b/libfuzzer/FuzzerRandom.h
@@ -18,27 +18,18 @@ class Random : public std::minstd_rand {
public:
Random(unsigned int seed) : std::minstd_rand(seed) {}
result_type operator()() { return this->std::minstd_rand::operator()(); }
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value, T>::type Rand() {
- return static_cast<T>(this->operator()());
- }
- size_t RandBool() { return this->operator()() % 2; }
+ size_t Rand() { return this->operator()(); }
+ size_t RandBool() { return Rand() % 2; }
size_t SkewTowardsLast(size_t n) {
size_t T = this->operator()(n * n);
- size_t Res = static_cast<size_t>(sqrt(T));
+ size_t Res = sqrt(T);
return Res;
}
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value, T>::type operator()(T n) {
- return n ? Rand<T>() % n : 0;
- }
- template <typename T>
- typename std::enable_if<std::is_integral<T>::value, T>::type
- operator()(T From, T To) {
+ size_t operator()(size_t n) { return n ? Rand() % n : 0; }
+ intptr_t operator()(intptr_t From, intptr_t To) {
assert(From < To);
- auto RangeSize = static_cast<unsigned long long>(To) -
- static_cast<unsigned long long>(From) + 1;
- return static_cast<T>(this->operator()(RangeSize) + From);
+ intptr_t RangeSize = To - From + 1;
+ return operator()(RangeSize) + From;
}
};
diff --git a/libfuzzer/FuzzerSHA1.cpp b/libfuzzer/FuzzerSHA1.cpp
index b05655c..2005dc7 100644
--- a/libfuzzer/FuzzerSHA1.cpp
+++ b/libfuzzer/FuzzerSHA1.cpp
@@ -134,13 +134,12 @@ void sha1_hashBlock(sha1nfo *s) {
s->state[4] += e;
}
-// Adds the least significant byte of |data|.
-void sha1_addUncounted(sha1nfo *s, uint32_t data) {
- uint8_t *const b = (uint8_t *)s->buffer;
+void sha1_addUncounted(sha1nfo *s, uint8_t data) {
+ uint8_t * const b = (uint8_t*) s->buffer;
#ifdef SHA_BIG_ENDIAN
- b[s->bufferOffset] = static_cast<uint8_t>(data);
+ b[s->bufferOffset] = data;
#else
- b[s->bufferOffset ^ 3] = static_cast<uint8_t>(data);
+ b[s->bufferOffset ^ 3] = data;
#endif
s->bufferOffset++;
if (s->bufferOffset == BLOCK_LENGTH) {
diff --git a/libfuzzer/FuzzerTracePC.cpp b/libfuzzer/FuzzerTracePC.cpp
index d808b9b..91e94d8 100644
--- a/libfuzzer/FuzzerTracePC.cpp
+++ b/libfuzzer/FuzzerTracePC.cpp
@@ -106,15 +106,6 @@ void TracePC::PrintModuleInfo() {
}
if (size_t NumExtraCounters = ExtraCountersEnd() - ExtraCountersBegin())
Printf("INFO: %zd Extra Counters\n", NumExtraCounters);
-
- size_t MaxFeatures = CollectFeatures([](uint32_t) {});
- if (MaxFeatures > std::numeric_limits<uint32_t>::max())
- Printf("WARNING: The coverage PC tables may produce up to %zu features.\n"
- "This exceeds the maximum 32-bit value. Some features may be\n"
- "ignored, and fuzzing may become less precise. If possible,\n"
- "consider refactoring the fuzzer into several smaller fuzzers\n"
- "linked against only a portion of the current target.\n",
- MaxFeatures);
}
ATTRIBUTE_NO_SANITIZE_ALL
@@ -365,7 +356,7 @@ void TracePC::AddValueForMemcmp(void *caller_pc, const void *s1, const void *s2,
uint8_t HammingDistance = 0;
for (; I < Len; I++) {
if (B1[I] != B2[I] || (StopAtZero && B1[I] == 0)) {
- HammingDistance = static_cast<uint8_t>(Popcountll(B1[I] ^ B2[I]));
+ HammingDistance = Popcountll(B1[I] ^ B2[I]);
break;
}
}
diff --git a/libfuzzer/FuzzerTracePC.h b/libfuzzer/FuzzerTracePC.h
index a937329..0090923 100644
--- a/libfuzzer/FuzzerTracePC.h
+++ b/libfuzzer/FuzzerTracePC.h
@@ -54,7 +54,7 @@ struct MemMemTable {
void Add(const uint8_t *Data, size_t Size) {
if (Size <= 2) return;
Size = std::min(Size, Word::GetMaxSize());
- auto Idx = SimpleFastHash(Data, Size) % kSize;
+ size_t Idx = SimpleFastHash(Data, Size) % kSize;
MemMemWords[Idx].Set(Data, Size);
}
const Word &Get(size_t Idx) {
@@ -79,7 +79,7 @@ class TracePC {
void SetPrintNewPCs(bool P) { DoPrintNewPCs = P; }
void SetPrintNewFuncs(size_t P) { NumPrintNewFuncs = P; }
void UpdateObservedPCs();
- template <class Callback> size_t CollectFeatures(Callback CB) const;
+ template <class Callback> void CollectFeatures(Callback CB) const;
void ResetMaps() {
ValueProfileMap.Reset();
@@ -193,7 +193,7 @@ size_t ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
Handle8bitCounter(FirstFeature, P - Begin, V);
// Iterate by Step bytes at a time.
- for (; P + Step <= End; P += Step)
+ for (; P < End; P += Step)
if (LargeType Bundle = *reinterpret_cast<const LargeType *>(P)) {
Bundle = HostToLE(Bundle);
for (size_t I = 0; I < Step; I++, Bundle >>= 8)
@@ -234,16 +234,16 @@ unsigned CounterToFeature(T Counter) {
return Bit;
}
-template <class Callback> // void Callback(uint32_t Feature)
-ATTRIBUTE_NO_SANITIZE_ADDRESS ATTRIBUTE_NOINLINE size_t
-TracePC::CollectFeatures(Callback HandleFeature) const {
+template <class Callback> // void Callback(size_t Feature)
+ATTRIBUTE_NO_SANITIZE_ADDRESS
+ATTRIBUTE_NOINLINE
+void TracePC::CollectFeatures(Callback HandleFeature) const {
auto Handle8bitCounter = [&](size_t FirstFeature,
size_t Idx, uint8_t Counter) {
if (UseCounters)
- HandleFeature(static_cast<uint32_t>(FirstFeature + Idx * 8 +
- CounterToFeature(Counter)));
+ HandleFeature(FirstFeature + Idx * 8 + CounterToFeature(Counter));
else
- HandleFeature(static_cast<uint32_t>(FirstFeature + Idx));
+ HandleFeature(FirstFeature + Idx);
};
size_t FirstFeature = 0;
@@ -263,18 +263,16 @@ TracePC::CollectFeatures(Callback HandleFeature) const {
if (UseValueProfileMask) {
ValueProfileMap.ForEach([&](size_t Idx) {
- HandleFeature(static_cast<uint32_t>(FirstFeature + Idx));
+ HandleFeature(FirstFeature + Idx);
});
FirstFeature += ValueProfileMap.SizeInBits();
}
// Step function, grows similar to 8 * Log_2(A).
- auto StackDepthStepFunction = [](size_t A) -> size_t {
- if (!A)
- return A;
- auto Log2 = Log(A);
- if (Log2 < 3)
- return A;
+ auto StackDepthStepFunction = [](uint32_t A) -> uint32_t {
+ if (!A) return A;
+ uint32_t Log2 = Log(A);
+ if (Log2 < 3) return A;
Log2 -= 3;
return (Log2 + 1) * 8 + ((A >> Log2) & 7);
};
@@ -282,13 +280,8 @@ TracePC::CollectFeatures(Callback HandleFeature) const {
assert(StackDepthStepFunction(1024 * 4) == 80);
assert(StackDepthStepFunction(1024 * 1024) == 144);
- if (auto MaxStackOffset = GetMaxStackOffset()) {
- HandleFeature(static_cast<uint32_t>(
- FirstFeature + StackDepthStepFunction(MaxStackOffset / 8)));
- FirstFeature += StackDepthStepFunction(std::numeric_limits<size_t>::max());
- }
-
- return FirstFeature;
+ if (auto MaxStackOffset = GetMaxStackOffset())
+ HandleFeature(FirstFeature + StackDepthStepFunction(MaxStackOffset / 8));
}
extern TracePC TPC;
diff --git a/libfuzzer/FuzzerUtil.cpp b/libfuzzer/FuzzerUtil.cpp
index 0518549..7eecb68 100644
--- a/libfuzzer/FuzzerUtil.cpp
+++ b/libfuzzer/FuzzerUtil.cpp
@@ -111,7 +111,7 @@ bool ParseOneDictionaryEntry(const std::string &Str, Unit *U) {
char Hex[] = "0xAA";
Hex[2] = Str[Pos + 2];
Hex[3] = Str[Pos + 3];
- U->push_back(static_cast<uint8_t>(strtol(Hex, nullptr, 16)));
+ U->push_back(strtol(Hex, nullptr, 16));
Pos += 3;
continue;
}
@@ -226,11 +226,10 @@ unsigned NumberOfCpuCores() {
return N;
}
-uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial) {
- uint64_t Res = Initial;
- const uint8_t *Bytes = static_cast<const uint8_t *>(Data);
+size_t SimpleFastHash(const uint8_t *Data, size_t Size) {
+ size_t Res = 0;
for (size_t i = 0; i < Size; i++)
- Res = Res * 11 + Bytes[i];
+ Res = Res * 11 + Data[i];
return Res;
}
diff --git a/libfuzzer/FuzzerUtil.h b/libfuzzer/FuzzerUtil.h
index a188a7b..e90be08 100644
--- a/libfuzzer/FuzzerUtil.h
+++ b/libfuzzer/FuzzerUtil.h
@@ -88,11 +88,9 @@ std::string DisassembleCmd(const std::string &FileName);
std::string SearchRegexCmd(const std::string &Regex);
-uint64_t SimpleFastHash(const void *Data, size_t Size, uint64_t Initial = 0);
+size_t SimpleFastHash(const uint8_t *Data, size_t Size);
-inline size_t Log(size_t X) {
- return static_cast<size_t>((sizeof(unsigned long long) * 8) - Clzll(X) - 1);
-}
+inline uint32_t Log(uint32_t X) { return 32 - Clz(X) - 1; }
inline size_t PageSize() { return 4096; }
inline uint8_t *RoundUpByPage(uint8_t *P) {
diff --git a/libfuzzer/FuzzerUtilFuchsia.cpp b/libfuzzer/FuzzerUtilFuchsia.cpp
index 5034b4a..af43946 100644
--- a/libfuzzer/FuzzerUtilFuchsia.cpp
+++ b/libfuzzer/FuzzerUtilFuchsia.cpp
@@ -515,7 +515,7 @@ int ExecuteCommand(const Command &Cmd) {
return rc;
}
- return static_cast<int>(Info.return_code);
+ return Info.return_code;
}
bool ExecuteCommand(const Command &BaseCmd, std::string *CmdOutput) {
diff --git a/libfuzzer/FuzzerUtilPosix.cpp b/libfuzzer/FuzzerUtilPosix.cpp
index 0446d73..afb7334 100644
--- a/libfuzzer/FuzzerUtilPosix.cpp
+++ b/libfuzzer/FuzzerUtilPosix.cpp
@@ -77,13 +77,10 @@ static void SetSigaction(int signum,
return;
}
- struct sigaction new_sigact = {};
- // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a
- // dedicated stack) in order to be able to detect stack overflows; keep the
- // flag if it's set.
- new_sigact.sa_flags = SA_SIGINFO | (sigact.sa_flags & SA_ONSTACK);
- new_sigact.sa_sigaction = callback;
- if (sigaction(signum, &new_sigact, nullptr)) {
+ sigact = {};
+ sigact.sa_flags = SA_SIGINFO;
+ sigact.sa_sigaction = callback;
+ if (sigaction(signum, &sigact, 0)) {
Printf("libFuzzer: sigaction failed with %d\n", errno);
exit(1);
}
diff --git a/libfuzzer/tests/FuzzedDataProviderUnittest.cpp b/libfuzzer/tests/FuzzedDataProviderUnittest.cpp
index ea6774e..99d9d8e 100644
--- a/libfuzzer/tests/FuzzedDataProviderUnittest.cpp
+++ b/libfuzzer/tests/FuzzedDataProviderUnittest.cpp
@@ -283,20 +283,6 @@ TEST(FuzzedDataProvider, ConsumeBool) {
EXPECT_EQ(false, DataProv.ConsumeBool());
}
-TEST(FuzzedDataProvider, PickValueInStdArray) {
- FuzzedDataProvider DataProv(Data, sizeof(Data));
- const std::array<int, 5> Array = {1, 2, 3, 4, 5};
- EXPECT_EQ(5, DataProv.PickValueInArray(Array));
- EXPECT_EQ(2, DataProv.PickValueInArray(Array));
- EXPECT_EQ(2, DataProv.PickValueInArray(Array));
- EXPECT_EQ(3, DataProv.PickValueInArray(Array));
- EXPECT_EQ(3, DataProv.PickValueInArray(Array));
- EXPECT_EQ(3, DataProv.PickValueInArray(Array));
- EXPECT_EQ(1, DataProv.PickValueInArray(Array));
- EXPECT_EQ(3, DataProv.PickValueInArray(Array));
- EXPECT_EQ(2, DataProv.PickValueInArray(Array));
-}
-
TEST(FuzzedDataProvider, PickValueInArray) {
FuzzedDataProvider DataProv(Data, sizeof(Data));
const int Array[] = {1, 2, 3, 4, 5};
diff --git a/libfuzzer/tests/FuzzerUnittest.cpp b/libfuzzer/tests/FuzzerUnittest.cpp
index 974a01f..d2b5cbb 100644
--- a/libfuzzer/tests/FuzzerUnittest.cpp
+++ b/libfuzzer/tests/FuzzerUnittest.cpp
@@ -614,80 +614,73 @@ TEST(Corpus, Distribution) {
}
}
-template <typename T> void EQ(const Vector<T> &A, const Vector<T> &B) {
- EXPECT_EQ(A, B);
+TEST(Merge, Bad) {
+ const char *kInvalidInputs[] = {
+ "",
+ "x",
+ "3\nx",
+ "2\n3",
+ "2\n2",
+ "2\n2\nA\n",
+ "2\n2\nA\nB\nC\n",
+ "0\n0\n",
+ "1\n1\nA\nFT 0",
+ "1\n1\nA\nSTARTED 1",
+ };
+ Merger M;
+ for (auto S : kInvalidInputs) {
+ // fprintf(stderr, "TESTING:\n%s\n", S);
+ EXPECT_FALSE(M.Parse(S, false));
+ }
}
-template <typename T> void EQ(const Set<T> &A, const Vector<T> &B) {
- EXPECT_EQ(A, Set<T>(B.begin(), B.end()));
+void EQ(const Vector<uint32_t> &A, const Vector<uint32_t> &B) {
+ EXPECT_EQ(A, B);
}
-void EQ(const Vector<MergeFileInfo> &A, const Vector<std::string> &B) {
- Set<std::string> a;
- for (const auto &File : A)
- a.insert(File.Name);
+void EQ(const Vector<std::string> &A, const Vector<std::string> &B) {
+ Set<std::string> a(A.begin(), A.end());
Set<std::string> b(B.begin(), B.end());
EXPECT_EQ(a, b);
}
-#define TRACED_EQ(A, ...) \
- { \
- SCOPED_TRACE(#A); \
- EQ(A, __VA_ARGS__); \
- }
-
-TEST(Merger, Parse) {
+static void Merge(const std::string &Input,
+ const Vector<std::string> Result,
+ size_t NumNewFeatures) {
Merger M;
+ Vector<std::string> NewFiles;
+ Set<uint32_t> NewFeatures, NewCov;
+ EXPECT_TRUE(M.Parse(Input, true));
+ EXPECT_EQ(NumNewFeatures, M.Merge({}, &NewFeatures, {}, &NewCov, &NewFiles));
+ EQ(NewFiles, Result);
+}
- const char *kInvalidInputs[] = {
- // Bad file numbers
- "",
- "x",
- "0\n0",
- "3\nx",
- "2\n3",
- "2\n2",
- // Bad file names
- "2\n2\nA\n",
- "2\n2\nA\nB\nC\n",
- // Unknown markers
- "2\n1\nA\nSTARTED 0\nBAD 0 0x0",
- // Bad file IDs
- "1\n1\nA\nSTARTED 1",
- "2\n1\nA\nSTARTED 0\nFT 1 0x0",
- };
- for (auto S : kInvalidInputs) {
- SCOPED_TRACE(S);
- EXPECT_FALSE(M.Parse(S, false));
- }
+TEST(Merge, Good) {
+ Merger M;
- // Parse initial control file
EXPECT_TRUE(M.Parse("1\n0\nAA\n", false));
- ASSERT_EQ(M.Files.size(), 1U);
+ EXPECT_EQ(M.Files.size(), 1U);
EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
EXPECT_EQ(M.Files[0].Name, "AA");
EXPECT_TRUE(M.LastFailure.empty());
EXPECT_EQ(M.FirstNotProcessedFile, 0U);
- // Parse control file that failed on first attempt
EXPECT_TRUE(M.Parse("2\n1\nAA\nBB\nSTARTED 0 42\n", false));
- ASSERT_EQ(M.Files.size(), 2U);
+ EXPECT_EQ(M.Files.size(), 2U);
EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
EXPECT_EQ(M.Files[0].Name, "AA");
EXPECT_EQ(M.Files[1].Name, "BB");
EXPECT_EQ(M.LastFailure, "AA");
EXPECT_EQ(M.FirstNotProcessedFile, 1U);
- // Parse control file that failed on later attempt
EXPECT_TRUE(M.Parse("3\n1\nAA\nBB\nC\n"
- "STARTED 0 1000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6 \n"
- "STARTED 2 1002\n"
- "",
- true));
- ASSERT_EQ(M.Files.size(), 3U);
+ "STARTED 0 1000\n"
+ "FT 0 1 2 3\n"
+ "STARTED 1 1001\n"
+ "FT 1 4 5 6 \n"
+ "STARTED 2 1002\n"
+ "", true));
+ EXPECT_EQ(M.Files.size(), 3U);
EXPECT_EQ(M.NumFilesInFirstCorpus, 1U);
EXPECT_EQ(M.Files[0].Name, "AA");
EXPECT_EQ(M.Files[0].Size, 1000U);
@@ -697,171 +690,82 @@ TEST(Merger, Parse) {
EXPECT_EQ(M.Files[2].Size, 1002U);
EXPECT_EQ(M.LastFailure, "C");
EXPECT_EQ(M.FirstNotProcessedFile, 3U);
- TRACED_EQ(M.Files[0].Features, {1, 2, 3});
- TRACED_EQ(M.Files[1].Features, {4, 5, 6});
-
- // Parse control file without features or PCs
- EXPECT_TRUE(M.Parse("2\n0\nAA\nBB\n"
- "STARTED 0 1000\n"
- "FT 0\n"
- "COV 0\n"
- "STARTED 1 1001\n"
- "FT 1\n"
- "COV 1\n"
- "",
- true));
- ASSERT_EQ(M.Files.size(), 2U);
- EXPECT_EQ(M.NumFilesInFirstCorpus, 0U);
- EXPECT_TRUE(M.LastFailure.empty());
- EXPECT_EQ(M.FirstNotProcessedFile, 2U);
- EXPECT_TRUE(M.Files[0].Features.empty());
- EXPECT_TRUE(M.Files[0].Cov.empty());
- EXPECT_TRUE(M.Files[1].Features.empty());
- EXPECT_TRUE(M.Files[1].Cov.empty());
+ EQ(M.Files[0].Features, {1, 2, 3});
+ EQ(M.Files[1].Features, {4, 5, 6});
+
+
+ Vector<std::string> NewFiles;
+ Set<uint32_t> NewFeatures, NewCov;
- // Parse features and PCs
EXPECT_TRUE(M.Parse("3\n2\nAA\nBB\nC\n"
- "STARTED 0 1000\n"
- "FT 0 1 2 3\n"
- "COV 0 11 12 13\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6\n"
- "COV 1 7 8 9\n"
- "STARTED 2 1002\n"
- "FT 2 6 1 3\n"
- "COV 2 16 11 13\n"
- "",
- true));
- ASSERT_EQ(M.Files.size(), 3U);
+ "STARTED 0 1000\nFT 0 1 2 3\n"
+ "STARTED 1 1001\nFT 1 4 5 6 \n"
+ "STARTED 2 1002\nFT 2 6 1 3 \n"
+ "", true));
+ EXPECT_EQ(M.Files.size(), 3U);
EXPECT_EQ(M.NumFilesInFirstCorpus, 2U);
EXPECT_TRUE(M.LastFailure.empty());
EXPECT_EQ(M.FirstNotProcessedFile, 3U);
- TRACED_EQ(M.Files[0].Features, {1, 2, 3});
- TRACED_EQ(M.Files[0].Cov, {11, 12, 13});
- TRACED_EQ(M.Files[1].Features, {4, 5, 6});
- TRACED_EQ(M.Files[1].Cov, {7, 8, 9});
- TRACED_EQ(M.Files[2].Features, {1, 3, 6});
- TRACED_EQ(M.Files[2].Cov, {16});
-}
-
-TEST(Merger, Merge) {
- Merger M;
- Set<uint32_t> Features, NewFeatures;
- Set<uint32_t> Cov, NewCov;
- Vector<std::string> NewFiles;
+ EQ(M.Files[0].Features, {1, 2, 3});
+ EQ(M.Files[1].Features, {4, 5, 6});
+ EQ(M.Files[2].Features, {1, 3, 6});
+ EXPECT_EQ(0U, M.Merge({}, &NewFeatures, {}, &NewCov, &NewFiles));
+ EQ(NewFiles, {});
- // Adds new files and features
- EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
- "STARTED 0 1000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6 \n"
- "STARTED 2 1002\n"
- "FT 2 6 1 3\n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U);
- TRACED_EQ(M.Files, {"A", "B", "C"});
- TRACED_EQ(NewFiles, {"A", "B"});
- TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
-
- // Doesn't return features or files in the initial corpus.
EXPECT_TRUE(M.Parse("3\n1\nA\nB\nC\n"
- "STARTED 0 1000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6 \n"
- "STARTED 2 1002\n"
- "FT 2 6 1 3\n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
- TRACED_EQ(M.Files, {"A", "B", "C"});
- TRACED_EQ(NewFiles, {"B"});
- TRACED_EQ(NewFeatures, {4, 5, 6});
-
- // No new features, so no new files
- EXPECT_TRUE(M.Parse("3\n2\nA\nB\nC\n"
- "STARTED 0 1000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6 \n"
- "STARTED 2 1002\n"
- "FT 2 6 1 3\n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 0U);
- TRACED_EQ(M.Files, {"A", "B", "C"});
- TRACED_EQ(NewFiles, {});
- TRACED_EQ(NewFeatures, {});
-
- // Can pass initial features and coverage.
- Features = {1, 2, 3};
- Cov = {};
- EXPECT_TRUE(M.Parse("2\n0\nA\nB\n"
- "STARTED 0 1000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6\n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
- TRACED_EQ(M.Files, {"A", "B"});
- TRACED_EQ(NewFiles, {"B"});
- TRACED_EQ(NewFeatures, {4, 5, 6});
- Features.clear();
- Cov.clear();
-
- // Parse smaller files first
- EXPECT_TRUE(M.Parse("3\n0\nA\nB\nC\n"
- "STARTED 0 2000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1001\n"
- "FT 1 4 5 6 \n"
- "STARTED 2 1002\n"
- "FT 2 6 1 3 \n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 6U);
- TRACED_EQ(M.Files, {"B", "C", "A"});
- TRACED_EQ(NewFiles, {"B", "C", "A"});
- TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6});
-
- EXPECT_TRUE(M.Parse("4\n0\nA\nB\nC\nD\n"
- "STARTED 0 2000\n"
- "FT 0 1 2 3\n"
- "STARTED 1 1101\n"
- "FT 1 4 5 6 \n"
- "STARTED 2 1102\n"
- "FT 2 6 1 3 100 \n"
- "STARTED 3 1000\n"
- "FT 3 1 \n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 7U);
- TRACED_EQ(M.Files, {"A", "B", "C", "D"});
- TRACED_EQ(NewFiles, {"D", "B", "C", "A"});
- TRACED_EQ(NewFeatures, {1, 2, 3, 4, 5, 6, 100});
-
- // For same sized file, parse more features first
- EXPECT_TRUE(M.Parse("4\n1\nA\nB\nC\nD\n"
- "STARTED 0 2000\n"
- "FT 0 4 5 6 7 8\n"
- "STARTED 1 1100\n"
- "FT 1 1 2 3 \n"
- "STARTED 2 1100\n"
- "FT 2 2 3 \n"
- "STARTED 3 1000\n"
- "FT 3 1 \n"
- "",
- true));
- EXPECT_EQ(M.Merge(Features, &NewFeatures, Cov, &NewCov, &NewFiles), 3U);
- TRACED_EQ(M.Files, {"A", "B", "C", "D"});
- TRACED_EQ(NewFiles, {"D", "B"});
- TRACED_EQ(NewFeatures, {1, 2, 3});
+ "STARTED 0 1000\nFT 0 1 2 3\n"
+ "STARTED 1 1001\nFT 1 4 5 6 \n"
+ "STARTED 2 1002\nFT 2 6 1 3\n"
+ "", true));
+ EQ(M.Files[0].Features, {1, 2, 3});
+ EQ(M.Files[1].Features, {4, 5, 6});
+ EQ(M.Files[2].Features, {1, 3, 6});
+ EXPECT_EQ(3U, M.Merge({}, &NewFeatures, {}, &NewCov, &NewFiles));
+ EQ(NewFiles, {"B"});
+
+ // Same as the above, but with InitialFeatures.
+ EXPECT_TRUE(M.Parse("2\n0\nB\nC\n"
+ "STARTED 0 1001\nFT 0 4 5 6 \n"
+ "STARTED 1 1002\nFT 1 6 1 3\n"
+ "", true));
+ EQ(M.Files[0].Features, {4, 5, 6});
+ EQ(M.Files[1].Features, {1, 3, 6});
+ Set<uint32_t> InitialFeatures;
+ InitialFeatures.insert(1);
+ InitialFeatures.insert(2);
+ InitialFeatures.insert(3);
+ EXPECT_EQ(3U, M.Merge(InitialFeatures, &NewFeatures, {}, &NewCov, &NewFiles));
+ EQ(NewFiles, {"B"});
}
-#undef TRACED_EQ
+TEST(Merge, Merge) {
+
+ Merge("3\n1\nA\nB\nC\n"
+ "STARTED 0 1000\nFT 0 1 2 3\n"
+ "STARTED 1 1001\nFT 1 4 5 6 \n"
+ "STARTED 2 1002\nFT 2 6 1 3 \n",
+ {"B"}, 3);
+
+ Merge("3\n0\nA\nB\nC\n"
+ "STARTED 0 2000\nFT 0 1 2 3\n"
+ "STARTED 1 1001\nFT 1 4 5 6 \n"
+ "STARTED 2 1002\nFT 2 6 1 3 \n",
+ {"A", "B", "C"}, 6);
+
+ Merge("4\n0\nA\nB\nC\nD\n"
+ "STARTED 0 2000\nFT 0 1 2 3\n"
+ "STARTED 1 1101\nFT 1 4 5 6 \n"
+ "STARTED 2 1102\nFT 2 6 1 3 100 \n"
+ "STARTED 3 1000\nFT 3 1 \n",
+ {"A", "B", "C", "D"}, 7);
+
+ Merge("4\n1\nA\nB\nC\nD\n"
+ "STARTED 0 2000\nFT 0 4 5 6 7 8\n"
+ "STARTED 1 1100\nFT 1 1 2 3 \n"
+ "STARTED 2 1100\nFT 2 2 3 \n"
+ "STARTED 3 1000\nFT 3 1 \n",
+ {"B", "D"}, 3);
+}
TEST(DFT, BlockCoverage) {
BlockCoverage Cov;
diff --git a/patches/Android.bp.patch b/patches/Android.bp.patch
new file mode 100644
index 0000000..c0d6fd7
--- /dev/null
+++ b/patches/Android.bp.patch
@@ -0,0 +1,25 @@
+diff --git a/Android.bp b/Android.bp
+index 86434dd..e565b86 100644
+--- a/Android.bp
++++ b/Android.bp
+@@ -1,17 +1,15 @@
+ // This file is generated by cargo2android.py --run --dependencies --device --features arbitrary-derive --patch patches/Android.bp.patch.
+
+-rust_library {
++rust_library_rlib {
+ name: "liblibfuzzer_sys",
+ host_supported: true,
+ crate_name: "libfuzzer_sys",
+ srcs: ["src/lib.rs"],
+ edition: "2018",
+ features: ["arbitrary-derive"],
+- rustlibs: [
++ rlibs: [
+ "libarbitrary",
+ ],
+- static_libs: ["libfuzzer"],
+- shared_libs: ["libstdc++"],
+ }
+
+ // dependent_library ["feature_list"]
+
diff --git a/src/lib.rs b/src/lib.rs
index 6badc39..59dfc47 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -12,14 +12,11 @@
#![deny(missing_docs, missing_debug_implementations)]
pub use arbitrary;
-use once_cell::sync::OnceCell;
extern "C" {
// We do not actually cross the FFI bound here.
#[allow(improper_ctypes)]
fn rust_fuzzer_test_input(input: &[u8]);
-
- fn LLVMFuzzerMutate(data: *mut u8, size: usize, max_size: usize) -> usize;
}
#[doc(hidden)]
@@ -38,9 +35,6 @@ pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
}
#[doc(hidden)]
-pub static RUST_LIBFUZZER_DEBUG_PATH: OnceCell<String> = OnceCell::new();
-
-#[doc(hidden)]
#[export_name = "LLVMFuzzerInitialize"]
pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize {
// Registers a panic hook that aborts the process before unwinding.
@@ -56,14 +50,6 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
default_hook(panic_info);
::std::process::abort();
}));
-
- // Initialize the `RUST_LIBFUZZER_DEBUG_PATH` cell with the path so it can be
- // reused with little overhead.
- if let Ok(path) = std::env::var("RUST_LIBFUZZER_DEBUG_PATH") {
- RUST_LIBFUZZER_DEBUG_PATH
- .set(path)
- .expect("Since this is initialize it is only called once so can never fail");
- }
0
}
@@ -98,9 +84,8 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
///
/// ```no_run
/// #![no_main]
-/// # mod foo {
///
-/// use libfuzzer_sys::{arbitrary::{Arbitrary, Error, Unstructured}, fuzz_target};
+/// use libfuzzer_sys::{arbitrary::{Arbitrary, Unstructured}, fuzz_target};
///
/// #[derive(Debug)]
/// pub struct Rgb {
@@ -109,8 +94,11 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
/// b: u8,
/// }
///
-/// impl<'a> Arbitrary<'a> for Rgb {
-/// fn arbitrary(raw: &mut Unstructured<'a>) -> Result<Self, Error> {
+/// impl Arbitrary for Rgb {
+/// fn arbitrary<U>(raw: &mut U) -> Result<Self, U::Error>
+/// where
+/// U: Unstructured + ?Sized
+/// {
/// let mut buf = [0; 3];
/// raw.fill_buffer(&mut buf)?;
/// let r = buf[0];
@@ -124,27 +112,16 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
/// fuzz_target!(|color: Rgb| {
/// my_crate::convert_color(color);
/// });
-/// # mod my_crate {
-/// # use super::Rgb;
-/// # pub fn convert_color(_: Rgb) {}
-/// # }
-/// # }
-/// ```
-///
-/// You can also enable the `arbitrary` crate's custom derive via this crate's
-/// `"arbitrary-derive"` cargo feature.
+/// # mod my_crate { fn convert_color(_: super::Rgb) {} }
#[macro_export]
macro_rules! fuzz_target {
(|$bytes:ident| $body:block) => {
- /// Auto-generated function
#[no_mangle]
pub extern "C" fn rust_fuzzer_test_input($bytes: &[u8]) {
// When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
// formatting of the input to that file. This is only intended for
// `cargo fuzz`'s use!
-
- // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization.
- if let Some(path) = $crate::RUST_LIBFUZZER_DEBUG_PATH.get() {
+ if let Ok(path) = std::env::var("RUST_LIBFUZZER_DEBUG_PATH") {
use std::io::Write;
let mut file = std::fs::File::create(path)
.expect("failed to create `RUST_LIBFUZZER_DEBUG_PATH` file");
@@ -162,10 +139,9 @@ macro_rules! fuzz_target {
};
(|$data:ident: $dty: ty| $body:block) => {
- /// Auto-generated function
#[no_mangle]
pub extern "C" fn rust_fuzzer_test_input(bytes: &[u8]) {
- use $crate::arbitrary::{Arbitrary, Unstructured};
+ use libfuzzer_sys::arbitrary::{Arbitrary, Unstructured};
// Early exit if we don't have enough bytes for the `Arbitrary`
// implementation. This helps the fuzzer avoid exploring all the
@@ -183,9 +159,7 @@ macro_rules! fuzz_target {
// When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
// formatting of the input to that file. This is only intended for
// `cargo fuzz`'s use!
-
- // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization.
- if let Some(path) = $crate::RUST_LIBFUZZER_DEBUG_PATH.get() {
+ if let Ok(path) = std::env::var("RUST_LIBFUZZER_DEBUG_PATH") {
use std::io::Write;
let mut file = std::fs::File::create(path)
.expect("failed to create `RUST_LIBFUZZER_DEBUG_PATH` file");
@@ -206,221 +180,3 @@ macro_rules! fuzz_target {
}
};
}
-
-/// Define a custom mutator.
-///
-/// This is optional, and libFuzzer will use its own, default mutation strategy
-/// if this is not provided.
-///
-/// You might consider using a custom mutator when your fuzz target is very
-/// particular about the shape of its input:
-///
-/// * You want to fuzz "deeper" than just the parser.
-/// * The input contains checksums that have to match the hash of some subset of
-/// the data or else the whole thing is invalid, and therefore mutating any of
-/// that subset means you need to recompute the checksums.
-/// * Small random changes to the input buffer make it invalid.
-///
-/// That is, a custom mutator is useful in similar situations where [a `T:
-/// Arbitrary` input type](macro.fuzz_target.html#arbitrary-input-types) is
-/// useful. Note that the two approaches are not mutually exclusive; you can use
-/// whichever is easier for your problem domain or both!
-///
-/// ## Implementation Contract
-///
-/// The original, unmodified input is given in `data[..size]`.
-///
-/// You must modify the data in place and return the new size.
-///
-/// The new size should not be greater than `max_size`. If this is not the case,
-/// then the `data` will be truncated to fit within `max_size`. Note that
-/// `max_size < size` is possible when shrinking test cases.
-///
-/// You must produce the same mutation given the same `seed`. Generally, when
-/// choosing what kind of mutation to make or where to mutate, you should start
-/// by creating a random number generator (RNG) that is seeded with the given
-/// `seed` and then consult the RNG whenever making a decision:
-///
-/// ```no_run
-/// #![no_main]
-///
-/// use rand::{rngs::StdRng, Rng, SeedableRng};
-///
-/// libfuzzer_sys::fuzz_mutator!(|data: &mut [u8], size: usize, max_size: usize, seed: u32| {
-/// let mut rng = StdRng::seed_from_u64(seed as u64);
-///
-/// # let first_mutation = |_, _, _, _| todo!();
-/// # let second_mutation = |_, _, _, _| todo!();
-/// # let third_mutation = |_, _, _, _| todo!();
-/// # let fourth_mutation = |_, _, _, _| todo!();
-/// // Choose which of our four supported kinds of mutations we want to make.
-/// match rng.gen_range(0..4) {
-/// 0 => first_mutation(rng, data, size, max_size),
-/// 1 => second_mutation(rng, data, size, max_size),
-/// 2 => third_mutation(rng, data, size, max_size),
-/// 3 => fourth_mutation(rng, data, size, max_size),
-/// _ => unreachable!()
-/// }
-/// });
-/// ```
-///
-/// ## Example: Compression
-///
-/// Consider a simple fuzz target that takes compressed data as input,
-/// decompresses it, and then asserts that the decompressed data doesn't begin
-/// with "boom". It is difficult for `libFuzzer` (or any other fuzzer) to crash
-/// this fuzz target because nearly all mutations it makes will invalidate the
-/// compression format. Therefore, we use a custom mutator that decompresses the
-/// raw input, mutates the decompressed data, and then recompresses it. This
-/// allows `libFuzzer` to quickly discover crashing inputs.
-///
-/// ```no_run
-/// #![no_main]
-///
-/// use flate2::{read::GzDecoder, write::GzEncoder, Compression};
-/// use libfuzzer_sys::{fuzz_mutator, fuzz_target};
-/// use std::io::{Read, Write};
-///
-/// fuzz_target!(|data: &[u8]| {
-/// // Decompress the input data and crash if it starts with "boom".
-/// if let Some(data) = decompress(data) {
-/// if data.starts_with(b"boom") {
-/// panic!();
-/// }
-/// }
-/// });
-///
-/// fuzz_mutator!(
-/// |data: &mut [u8], size: usize, max_size: usize, _seed: u32| {
-/// // Decompress the input data. If that fails, use a dummy value.
-/// let mut decompressed = decompress(&data[..size]).unwrap_or_else(|| b"hi".to_vec());
-///
-/// // Mutate the decompressed data with `libFuzzer`'s default mutator. Make
-/// // the `decompressed` vec's extra capacity available for insertion
-/// // mutations via `resize`.
-/// let len = decompressed.len();
-/// let cap = decompressed.capacity();
-/// decompressed.resize(cap, 0);
-/// let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len, cap);
-///
-/// // Recompress the mutated data.
-/// let compressed = compress(&decompressed[..new_decompressed_size]);
-///
-/// // Copy the recompressed mutated data into `data` and return the new size.
-/// let new_size = std::cmp::min(max_size, compressed.len());
-/// data[..new_size].copy_from_slice(&compressed[..new_size]);
-/// new_size
-/// }
-/// );
-///
-/// fn decompress(compressed_data: &[u8]) -> Option<Vec<u8>> {
-/// let mut decoder = GzDecoder::new(compressed_data);
-/// let mut decompressed = Vec::new();
-/// if decoder.read_to_end(&mut decompressed).is_ok() {
-/// Some(decompressed)
-/// } else {
-/// None
-/// }
-/// }
-///
-/// fn compress(data: &[u8]) -> Vec<u8> {
-/// let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
-/// encoder
-/// .write_all(data)
-/// .expect("writing into a vec is infallible");
-/// encoder.finish().expect("writing into a vec is infallible")
-/// }
-/// ```
-///
-/// This example is inspired by [a similar example from the official `libFuzzer`
-/// docs](https://github.com/google/fuzzing/blob/master/docs/structure-aware-fuzzing.md#example-compression).
-///
-/// ## More Example Ideas
-///
-/// * A PNG custom mutator that decodes a PNG, mutates the image, and then
-/// re-encodes the mutated image as a new PNG.
-///
-/// * A [`serde`](https://serde.rs/) custom mutator that deserializes your
-/// structure, mutates it, and then reserializes it.
-///
-/// * A Wasm binary custom mutator that inserts, replaces, and removes a
-/// bytecode instruction in a function's body.
-///
-/// * An HTTP request custom mutator that inserts, replaces, and removes a
-/// header from an HTTP request.
-#[macro_export]
-macro_rules! fuzz_mutator {
- (
- |
- $data:ident : &mut [u8] ,
- $size:ident : usize ,
- $max_size:ident : usize ,
- $seed:ident : u32 $(,)*
- |
- $body:block
- ) => {
- /// Auto-generated function.
- #[export_name = "LLVMFuzzerCustomMutator"]
- pub fn rust_fuzzer_custom_mutator(
- $data: *mut u8,
- $size: usize,
- $max_size: usize,
- $seed: std::os::raw::c_uint,
- ) -> usize {
- // Depending on if we are growing or shrinking the test case, `size`
- // might be larger or smaller than `max_size`. The `data`'s capacity
- // is the maximum of the two.
- let len = std::cmp::max($max_size, $size);
- let $data: &mut [u8] = unsafe { std::slice::from_raw_parts_mut($data, len) };
-
- // `unsigned int` is generally a `u32`, but not on all targets. Do
- // an infallible (and potentially lossy, but that's okay because it
- // preserves determinism) conversion.
- let $seed = $seed as u32;
-
- // Truncate the new size if it is larger than the max.
- let new_size = { $body };
- std::cmp::min(new_size, $max_size)
- }
- };
-}
-
-/// The default `libFuzzer` mutator.
-///
-/// You generally don't have to use this at all unless you're defining a
-/// custom mutator with [the `fuzz_mutator!` macro][crate::fuzz_mutator].
-///
-/// Mutates `data[..size]` in place such that the mutated data is no larger than
-/// `max_size` and returns the new size of the mutated data.
-///
-/// To only allow shrinking mutations, make `max_size < size`.
-///
-/// To additionally allow mutations that grow the size of the data, make
-/// `max_size > size`.
-///
-/// Both `size` and `max_size` must be less than or equal to `data.len()`.
-///
-/// # Example
-///
-/// ```no_run
-/// // Create some data in a buffer.
-/// let mut data = vec![0; 128];
-/// data[..b"hello".len()].copy_from_slice(b"hello");
-///
-/// // Ask `libFuzzer` to mutate the data. By setting `max_size` to our buffer's
-/// // full length, we are allowing `libFuzzer` to perform mutations that grow
-/// // the size of the data, such as insertions.
-/// let size = b"hello".len();
-/// let max_size = data.len();
-/// let new_size = libfuzzer_sys::fuzzer_mutate(&mut data, size, max_size);
-///
-/// // Get the mutated data out of the buffer.
-/// let mutated_data = &data[..new_size];
-/// ```
-pub fn fuzzer_mutate(data: &mut [u8], size: usize, max_size: usize) -> usize {
- assert!(size <= data.len());
- assert!(max_size <= data.len());
- let new_size = unsafe { LLVMFuzzerMutate(data.as_mut_ptr(), size, max_size) };
- assert!(new_size <= data.len());
- new_size
-}