// Copyright 2021 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package fuzz// byteSliceRemoveBytes removes a random chunk of bytes from b.func byteSliceRemoveBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := + .chooseLen(len()-)copy([:], [:]) = [:len()-(-)]return}// byteSliceInsertRandomBytes inserts a chunk of random bytes into b at a random// position.func byteSliceInsertRandomBytes( *mutator, []byte) []byte { := .rand(len() + 1) := .chooseLen(1024)iflen()+ >= cap() {returnnil } = [:len()+]copy([+:], [:])for := 0; < ; ++ { [+] = byte(.rand(256)) }return}// byteSliceDuplicateBytes duplicates a chunk of bytes in b and inserts it into// a random position.func byteSliceDuplicateBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := .rand(len())for == { = .rand(len()) } := .chooseLen(len() - )// Use the end of the slice as scratch space to avoid doing an // allocation. If the slice is too small abort and try something // else.iflen()+(*2) >= cap() {returnnil } := len()// Increase the size of b to fit the duplicated block as well as // some extra working space = [:+(*2)]// Copy the block of bytes we want to duplicate to the end of the // slicecopy([+:], [:+])// Shift the bytes after the splice point n positions to the right // to make room for the new blockcopy([+:+], [:])// Insert the duplicate block into the splice pointcopy([:], [+:]) = [:+]return}// byteSliceOverwriteBytes overwrites a chunk of b with another chunk of b.func byteSliceOverwriteBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := .rand(len())for == { = .rand(len()) } := .chooseLen(len() - - 1)copy([:], [:+])return}// byteSliceBitFlip flips a random bit in a random byte in b.func byteSliceBitFlip( *mutator, []byte) []byte {iflen() == 0 {returnnil } := .rand(len()) [] ^= 1 << uint(.rand(8))return}// byteSliceXORByte XORs a random byte in b with a random value.func byteSliceXORByte( *mutator, []byte) []byte {iflen() == 0 {returnnil } := .rand(len())// In order to avoid a no-op (where the random value matches // the existing value), use XOR instead of just setting to // the random value. [] ^= byte(1 + .rand(255))return}// byteSliceSwapByte swaps two random bytes in b.func byteSliceSwapByte( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := .rand(len())for == { = .rand(len()) } [], [] = [], []return}// byteSliceArithmeticUint8 adds/subtracts from a random byte in b.func byteSliceArithmeticUint8( *mutator, []byte) []byte {iflen() == 0 {returnnil } := .rand(len()) := byte(.rand(35) + 1)if .r.bool() { [] += } else { [] -= }return}// byteSliceArithmeticUint16 adds/subtracts from a random uint16 in b.func byteSliceArithmeticUint16( *mutator, []byte) []byte {iflen() < 2 {returnnil } := uint16(.rand(35) + 1)if .r.bool() { = 0 - } := .rand(len() - 1) := .randByteOrder() .PutUint16([:], .Uint16([:])+)return}// byteSliceArithmeticUint32 adds/subtracts from a random uint32 in b.func byteSliceArithmeticUint32( *mutator, []byte) []byte {iflen() < 4 {returnnil } := uint32(.rand(35) + 1)if .r.bool() { = 0 - } := .rand(len() - 3) := .randByteOrder() .PutUint32([:], .Uint32([:])+)return}// byteSliceArithmeticUint64 adds/subtracts from a random uint64 in b.func byteSliceArithmeticUint64( *mutator, []byte) []byte {iflen() < 8 {returnnil } := uint64(.rand(35) + 1)if .r.bool() { = 0 - } := .rand(len() - 7) := .randByteOrder() .PutUint64([:], .Uint64([:])+)return}// byteSliceOverwriteInterestingUint8 overwrites a random byte in b with an interesting// value.func byteSliceOverwriteInterestingUint8( *mutator, []byte) []byte {iflen() == 0 {returnnil } := .rand(len()) [] = byte(interesting8[.rand(len(interesting8))])return}// byteSliceOverwriteInterestingUint16 overwrites a random uint16 in b with an interesting// value.func byteSliceOverwriteInterestingUint16( *mutator, []byte) []byte {iflen() < 2 {returnnil } := .rand(len() - 1) := uint16(interesting16[.rand(len(interesting16))]) .randByteOrder().PutUint16([:], )return}// byteSliceOverwriteInterestingUint32 overwrites a random uint16 in b with an interesting// value.func byteSliceOverwriteInterestingUint32( *mutator, []byte) []byte {iflen() < 4 {returnnil } := .rand(len() - 3) := uint32(interesting32[.rand(len(interesting32))]) .randByteOrder().PutUint32([:], )return}// byteSliceInsertConstantBytes inserts a chunk of constant bytes into a random position in b.func byteSliceInsertConstantBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len())// TODO(rolandshoemaker,katiehockman): 4096 was mainly picked // randomly. We may want to either pick a much larger value // (AFL uses 32768, paired with a similar impl to chooseLen // which biases towards smaller lengths that grow over time), // or set the max based on characteristics of the corpus // (libFuzzer sets a min/max based on the min/max size of // entries in the corpus and then picks uniformly from // that range). := .chooseLen(4096)iflen()+ >= cap() {returnnil } = [:len()+]copy([+:], [:]) := byte(.rand(256))for := ; < +; ++ { [] = }return}// byteSliceOverwriteConstantBytes overwrites a chunk of b with constant bytes.func byteSliceOverwriteConstantBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := .chooseLen(len() - ) := byte(.rand(256))for := ; < +; ++ { [] = }return}// byteSliceShuffleBytes shuffles a chunk of bytes in b.func byteSliceShuffleBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := .chooseLen(len() - )if <= 2 {returnnil }// Start at the end of the range, and iterate backwards // to dst, swapping each element with another element in // dst:dst+n (Fisher-Yates shuffle).for := - 1; > 0; -- { := .rand( + 1) [+], [+] = [+], [+] }return}// byteSliceSwapBytes swaps two chunks of bytes in b.func byteSliceSwapBytes( *mutator, []byte) []byte {iflen() <= 1 {returnnil } := .rand(len()) := .rand(len())for == { = .rand(len()) }// Choose the random length as len(b) - max(src, dst) // so that we don't attempt to swap a chunk that extends // beyond the end of the slice := if > { = } := .chooseLen(len() - - 1)// Check that neither chunk intersect, so that we don't end up // duplicating parts of the input, rather than swapping themif > && + >= || > && + >= {returnnil }// Use the end of the slice as scratch space to avoid doing an // allocation. If the slice is too small abort and try something // else.iflen()+ >= cap() {returnnil } := len() = [:+]copy([:], [:+])copy([:], [:+])copy([:], [:]) = [:]return}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.