Skip to content

Commit

Permalink
Adding PFFFT seed corpus generation. (#1790)
Browse files Browse the repository at this point in the history
  • Loading branch information
alebzk authored and oliverchang committed Sep 4, 2018
1 parent dc0bb58 commit 0d5ed7b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 1 deletion.
3 changes: 2 additions & 1 deletion projects/pffft/Dockerfile
Expand Up @@ -16,9 +16,10 @@

FROM gcr.io/oss-fuzz-base/base-builder
MAINTAINER alessiob@webrtc.org
RUN apt-get update && apt-get install -y mercurial
RUN apt-get update && apt-get install -y mercurial python-numpy
RUN hg clone https://bitbucket.org/jpommier/pffft $SRC/pffft
WORKDIR pffft
COPY build.sh $SRC
# TODO(alessiob): Move the fuzzing source code to pffft upstream.
COPY generate_seed_corpus.py $SRC/pffft
COPY pffft_fuzzer.cc $SRC/pffft
24 changes: 24 additions & 0 deletions projects/pffft/build.sh
Expand Up @@ -18,11 +18,35 @@
SRC_DIR=$SRC/pffft
cd $WORK

# Deploy the seed corpus.
SEED_CORPUS_ZIP_PATH=$OUT/pffft_fuzzers_seed_corpus.zip
if [ -d seed_corpus_tmp ]; then
rm -fr seed_corpus_tmp
fi
mkdir seed_corpus_tmp
python $SRC_DIR/generate_seed_corpus.py seed_corpus_tmp
cd seed_corpus_tmp
zip -q $SEED_CORPUS_ZIP_PATH ./*
cd ..
rm -fr seed_corpus_tmp

build_fuzzer() {
# Aliases for the arguments.
fft_transform=$1

# Fuzzer name.
fuzz_target_name=pffft_${fft_transform,,}_fuzzer

# Add a symbolic link for the seed corpus (same corpus for all the
# generated fuzzers).
ls -la $OUT/*.zip
FUZZER_SEED_CORPUS_PATH=$OUT/${fuzz_target_name}_seed_corpus.zip
if [ -e $FUZZER_SEED_CORPUS_PATH ]; then
rm $FUZZER_SEED_CORPUS_PATH
fi
ln -s $SEED_CORPUS_ZIP_PATH $FUZZER_SEED_CORPUS_PATH

# Compile fuzzer.
$CXX $CXXFLAGS -std=c++11 -msse2 \
-DTRANSFORM_${fft_transform} \
$SRC/pffft/pffft.c $SRC/pffft/pffft_fuzzer.cc \
Expand Down
59 changes: 59 additions & 0 deletions projects/pffft/generate_seed_corpus.py
@@ -0,0 +1,59 @@
from __future__ import division
from __future__ import print_function

import os
import sys

import numpy as np

MAX_INPUT_SIZE = int(1e6)
MAX_FLOAT32 = np.finfo(np.float32).max

def IsValidSize(n):
if n == 0:
return False
# PFFFT only supports transforms for inputs of length N of the form
# N = (2^a)*(3^b)*(5^c) where a >= 5, b >=0, c >= 0.
FACTORS = [2, 3, 5]
factorization = [0, 0, 0]
for i, factor in enumerate(FACTORS):
while n % factor == 0:
n = n // factor
factorization[i] += 1
return factorization[0] >= 5 and n == 1


def main():
if len(sys.argv) < 2:
print('Usage: %s <path to output directory>' % sys.argv[0])
sys.exit(1)

output_path = sys.argv[1]
if not os.path.exists(output_path):
print('The output path does not exists.')
sys.exit(2)

# List of valid input sizes.
N = [n for n in range(MAX_INPUT_SIZE) if IsValidSize(n)]

# Set the seed to always generate the same random data.
np.random.seed(0)

# Generate different types of input arrays for each target length.
for n in N:
# Zeros.
z = np.zeros(n, np.float32)
z.tofile(os.path.join(output_path, 'zeros_%d' % n))
# Max float 32.
m = np.ones(n, np.float32) * MAX_FLOAT32
m.tofile(os.path.join(output_path, 'max_%d' % n))
# Random values in the s16 range.
rnd_s16 = 32768.0 * 2.0 * (np.random.rand(n) - 1.0)
rnd_s16 = rnd_s16.astype(np.float32)
rnd_s16.tofile(os.path.join(output_path, 'rnd_s16_%d' % n))

sys.exit(0)


if __name__ == '__main__':
main()

0 comments on commit 0d5ed7b

Please sign in to comment.