diff --git a/projects/bottleneck/Dockerfile b/projects/bottleneck/Dockerfile new file mode 100644 index 000000000..82f70d88f --- /dev/null +++ b/projects/bottleneck/Dockerfile @@ -0,0 +1,26 @@ +# Copyright 2022 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. +# +################################################################################ + +FROM gcr.io/oss-fuzz-base/base-builder-python +RUN apt-get update && apt-get install -y make autoconf automake libtool +RUN pip3 install cython +RUN git clone https://github.com/numpy/numpy && cd numpy && git submodule update --init +RUN cd $SRC/numpy && \ + pip3 install . && \ + python3 setup.py install +RUN git clone --depth 1 https://github.com/pydata/bottleneck +WORKDIR bottleneck +COPY build.sh *.py $SRC/ diff --git a/projects/bottleneck/build.sh b/projects/bottleneck/build.sh new file mode 100755 index 000000000..ebf315d32 --- /dev/null +++ b/projects/bottleneck/build.sh @@ -0,0 +1,26 @@ +#!/bin/bash -eu +# Copyright 2022 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. +# +################################################################################ + + +cd $SRC/bottleneck +pip3 install . +python3 setup.py install + +# Build fuzzers and put them in $OUT/ +for fuzzer in $(find $SRC -name 'fuzz_*.py'); do + compile_python_fuzzer $fuzzer +done diff --git a/projects/bottleneck/fuzz_bn.py b/projects/bottleneck/fuzz_bn.py new file mode 100644 index 000000000..389bf4904 --- /dev/null +++ b/projects/bottleneck/fuzz_bn.py @@ -0,0 +1,93 @@ +#!/usr/bin/python3 +# Copyright 2022 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. +"""Scalar equivalene checker""" + +import os +import sys +import atheris + +import numpy as np +from numpy.testing import assert_array_almost_equal +import bottleneck as bn + + +def gen_random_array(data, fdp = None): + if fdp is None: + fdp = atheris.FuzzedDataProvider(data) + l1 = list() + for i in range(fdp.ConsumeIntInRange(5, 3000)): + l1.append(fdp.ConsumeIntInRange(1,10000)) + a = np.array(l1) + return a + +def TestOneInput(data): + """Tests scalar equivalence and also move operations""" + fdp = atheris.FuzzedDataProvider(data) + a = gen_random_array(data, fdp) + + func_pairs = [ + (bn.nansum, bn.slow.nansum), + (bn.nanmean, bn.slow.nanmean), + (bn.nanstd, bn.slow.nanstd), + (bn.nanvar, bn.slow.nanvar), + (bn.nanmin, bn.slow.nanmin), + (bn.median, bn.slow.median), + (bn.nanmedian, bn.slow.nanmedian), + (bn.ss, bn.slow.ss), + (bn.nanargmin, bn.slow.nanargmin), + (bn.nanargmax, bn.slow.nanargmax), + (bn.anynan, bn.slow.anynan), + (bn.allnan, bn.slow.allnan), + ] + + idx = 0 + for func0, func1 in func_pairs: + idx = idx + 1 + actual = func0(a) + desired = func1(a) + assert_array_almost_equal( + actual, + desired, + err_msg="Failed scalar equivalence" + ) + + + # Test move operations + window = fdp.ConsumeIntInRange(2, 50) + min_count = fdp.ConsumeIntInRange(1, window) + actual = bn.move_median( + a, + window=window, + min_count = fdp.ConsumeIntInRange(1,100) + ) + desired = bn.slow.move_median( + a, + window=window, + min_count=fdp.ConsumeIntInRange(1, 100) + ) + assert_array_almost_equal( + actual, + desired, + err_msg="Failed move operation" + ) + + +def main(): + atheris.instrument_all() + atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True) + atheris.Fuzz() + +if __name__ == "__main__": + main() diff --git a/projects/bottleneck/project.yaml b/projects/bottleneck/project.yaml new file mode 100644 index 000000000..9f5453254 --- /dev/null +++ b/projects/bottleneck/project.yaml @@ -0,0 +1,10 @@ +homepage: "https://github.com/pydata/bottleneck" +language: python +main_repo: "https://github.com/pydata/bottleneck" +fuzzing_engines: + - libfuzzer +sanitizers: + - address + - undefined +vendor_ccs: + - david@adalogics.com