aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Arthur Chan <gamease@hotmail.com>2022-06-28 01:17:07 +0100
committerGravatar GitHub <noreply@github.com>2022-06-28 01:17:07 +0100
commite7af68a230d7d64407203c0ffd5c9ee1af75edb3 (patch)
treeb95dd0ae13be01167c8b0358b11e33b66c86600f
parent65bc9c9ceadca5dc852615efff12028794165cb9 (diff)
openpyxl: Initial integration (#7772)
* openpyxl: Initial integration Build initial fuzzer * Fix fuzzer * Fix fuzzer * Fix fuzzer * Fix fuzzer comments * Create new fuzzers - fuzz_basic.py - Basic workbook fuzzer - fuzz_load.py - File loading fuzzer - fuzz_chart.py - Chart fuzzer - fuzz_comment.py - Sheet comments fuzzer - fuzz_formulae.py - Formulae parsing fuzzer - fuzz_sort.py - Data sort and filter fuzzer - fuzz_sheet.py - Worksheet management fuzzer - fuzz_cellutil.py - Cell utils fuzzer * Fix project contact
-rw-r--r--projects/openpyxl/Dockerfile26
-rw-r--r--projects/openpyxl/build.sh24
-rw-r--r--projects/openpyxl/fuzz_basic.py42
-rw-r--r--projects/openpyxl/fuzz_cellutil.py58
-rw-r--r--projects/openpyxl/fuzz_chart.py81
-rw-r--r--projects/openpyxl/fuzz_comment.py47
-rw-r--r--projects/openpyxl/fuzz_formulae.py37
-rw-r--r--projects/openpyxl/fuzz_load.py44
-rw-r--r--projects/openpyxl/fuzz_sheet.py74
-rw-r--r--projects/openpyxl/fuzz_sort.py42
-rw-r--r--projects/openpyxl/project.yaml13
11 files changed, 488 insertions, 0 deletions
diff --git a/projects/openpyxl/Dockerfile b/projects/openpyxl/Dockerfile
new file mode 100644
index 00000000..e83f9c59
--- /dev/null
+++ b/projects/openpyxl/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 install mercurial -y
+RUN pip3 install --upgrade pip
+
+RUN hg clone https://foss.heptapod.net/openpyxl/openpyxl
+WORKDIR openpyxl
+
+COPY build.sh fuzz_*.py $SRC/
+
diff --git a/projects/openpyxl/build.sh b/projects/openpyxl/build.sh
new file mode 100644
index 00000000..6da18d63
--- /dev/null
+++ b/projects/openpyxl/build.sh
@@ -0,0 +1,24 @@
+#!/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.
+#
+################################################################################
+
+# Build and install project (using current CFLAGS, CXXFLAGS).
+pip3 install --upgrade pip
+pip3 install .
+
+for fuzzer in $(find $SRC -name 'fuzz_*.py'); do
+ compile_python_fuzzer $fuzzer
+done
diff --git a/projects/openpyxl/fuzz_basic.py b/projects/openpyxl/fuzz_basic.py
new file mode 100644
index 00000000..a8935315
--- /dev/null
+++ b/projects/openpyxl/fuzz_basic.py
@@ -0,0 +1,42 @@
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ import openpyxl
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+ wb = openpyxl.Workbook()
+ ws = wb.active
+
+ ws['A%d'%fdp.ConsumeIntInRange(1,sys.maxsize)] = fdp.ConsumeInt(10)
+ ws.append(fdp.ConsumeIntList(3,5))
+
+ ws['B%d'%fdp.ConsumeIntInRange(1,sys.maxsize)] = fdp.ConsumeUnicode(10)
+ ws['C%d'%fdp.ConsumeIntInRange(1,sys.maxsize)] = fdp.ConsumeBytes(10)
+ ws['D%d'%fdp.ConsumeIntInRange(1,sys.maxsize)] = fdp.ConsumeString(10)
+ ws['E%d'%fdp.ConsumeIntInRange(1,sys.maxsize)] = fdp.ConsumeFloat()
+ ws['F%d'%fdp.ConsumeIntInRange(1,sys.maxsize)] = fdp.ConsumeBool()
+
+ wb.save('%s.xlsx'%fdp.ConsumeString(10))
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_cellutil.py b/projects/openpyxl/fuzz_cellutil.py
new file mode 100644
index 00000000..3d41fdd2
--- /dev/null
+++ b/projects/openpyxl/fuzz_cellutil.py
@@ -0,0 +1,58 @@
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ import openpyxl.utils.cell as cell
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+
+ try:
+ cell.absolute_coordinate(fdp.ConsumeString(20))
+ cell.cols_from_range(fdp.ConsumeString(20))
+ cell.column_index_from_string(fdp.ConsumeString(20))
+ cell.coordinate_from_string(fdp.ConsumeString(20))
+ cell.coordinate_to_tuple(fdp.ConsumeString(20))
+ cell.get_column_interval(fdp.ConsumeInt(10),fdp.ConsumeInt(10))
+ cell.get_column_letter(fdp.ConsumeInt(10))
+ cell.quote_sheetname(fdp.ConsumeString(20))
+ cell.range_boundaries(fdp.ConsumeString(20))
+ cell.range_to_tuple(fdp.ConsumeString(20))
+ cell.rows_from_range(fdp.ConsumeString(20))
+ except ValueError as e:
+ error_list = [
+ "is not a valid coordinate range",
+ "Invalid column index",
+ "is not a valid column name",
+ "is not a valid coordinate or range",
+ "Value must be of the form sheetname!A1:E4"
+ ]
+ expected_error = False
+ for error in error_list:
+ if error in str(e):
+ expected_error = True
+ if not expected_error:
+ raise e
+ except CellCoordinatesException:
+ pass
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_chart.py b/projects/openpyxl/fuzz_chart.py
new file mode 100644
index 00000000..48001f69
--- /dev/null
+++ b/projects/openpyxl/fuzz_chart.py
@@ -0,0 +1,81 @@
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ from openpyxl import Workbook
+ from openpyxl.chart import (
+ AreaChart,
+ AreaChart3D,
+ BarChart,
+ BarChart3D,
+ LineChart,
+ LineChart3D,
+ Reference,
+ Series
+ )
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+
+ wb = Workbook()
+ ws = wb.active
+ cs = wb.create_chartsheet()
+
+ choice = fdp.ConsumeIntInRange(1,6)
+ chart = AreaChart()
+
+ if choice == 2:
+ chart = AreaChart3D()
+ if choice == 3:
+ chart = BarChart()
+ chart.type = "bar" if fdp.ConsumeBool() else "col"
+ chart.shape = 4
+ if choice == 4:
+ chart = BarChart3D()
+ chart.type = "bar" if fdp.ConsumeBool() else "col"
+ chart.shape = 4
+ if choice == 5:
+ chart = LineChart()
+ chart.legend = None
+ if choice == 6:
+ chart = LineChart3D()
+ chart.legend = None
+
+ #Chart basic settings
+ chart.title = fdp.ConsumeString(10)
+ chart.style = 13
+ chart.x_axis.title = fdp.ConsumeString(10)
+ chart.y_axis.title = fdp.ConsumeString(10)
+
+ #Chart data
+ ws.append(['Col1', 'Col2', 'Col3'])
+ for i in range(2,8):
+ ws.append([i,fdp.ConsumeIntInRange(1,100),fdp.ConsumeIntInRange(1,100)])
+
+ chart.add_data(Reference(ws, min_col=2, min_row=1, max_col=3, max_row=7), titles_from_data=True)
+ chart.set_categories(Reference(ws, min_col=1, min_row=1, max_row=7))
+
+ #Random add chart to worksheet or chartsheet
+ ws.add_chart(chart, "A10") if fdp.ConsumeBool() else cs.add_chart(chart)
+ wb.save('%s.xlsx'%fdp.ConsumeString(10))
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_comment.py b/projects/openpyxl/fuzz_comment.py
new file mode 100644
index 00000000..e332f86d
--- /dev/null
+++ b/projects/openpyxl/fuzz_comment.py
@@ -0,0 +1,47 @@
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ from openpyxl import Workbook
+ from openpyxl.comments import Comment
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+
+ wb = Workbook()
+ ws = wb.active
+
+ #Set Comment
+ c1 = ws['A1'].comment
+ c1 = Comment(fdp.ConsumeString(10),fdp.ConsumeString(10))
+ c1.width = 300
+ c1.height = 50
+ ws['A1'].comment = c1
+
+ #Double assign comment
+ c2 = Comment(fdp.ConsumeString(10),fdp.ConsumeString(10))
+ ws['B1'].comment = c2
+ ws['C1'].comment = c2
+
+ wb.save('%s.xlsx'%fdp.ConsumeString(10))
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_formulae.py b/projects/openpyxl/fuzz_formulae.py
new file mode 100644
index 00000000..845e9e48
--- /dev/null
+++ b/projects/openpyxl/fuzz_formulae.py
@@ -0,0 +1,37 @@
+
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ from openpyxl.formula import Tokenizer
+ from openpyxl.formula.translate import Translator
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+
+ #Initial tokenizer for random string and process it
+ Tokenizer(fdp.ConsumeString(200))
+
+ #Translate random string formulae
+ Translator(fdp.ConsumeString(200), origin="A1").translate_formula("B2")
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_load.py b/projects/openpyxl/fuzz_load.py
new file mode 100644
index 00000000..ebf90e9c
--- /dev/null
+++ b/projects/openpyxl/fuzz_load.py
@@ -0,0 +1,44 @@
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ import zipfile
+ import openpyxl
+
+def TestInput(data):
+ temp_file = "test.xlsx"
+ with open(temp_file, "wb") as fd:
+ fd.write(data)
+
+ try:
+ wb2 = openpyxl.load_workbook(temp_file)
+ except (zipfile.BadZipFile ,OSError) as e:
+ pass
+ except KeyError as e:
+ if "There is no item named '[Content_Types].xml' in the archive" in str(e):
+ #Not related to this fuzzing - possibly caused by known issue of wrong exception type as below
+ #https://foss.heptapod.net/openpyxl/openpyxl/-/issues/1061
+ pass
+ else:
+ raise(e)
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_sheet.py b/projects/openpyxl/fuzz_sheet.py
new file mode 100644
index 00000000..906086fb
--- /dev/null
+++ b/projects/openpyxl/fuzz_sheet.py
@@ -0,0 +1,74 @@
+#!/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.
+
+import atheris
+import sys
+import datetime
+with atheris.instrument_imports():
+ from openpyxl import Workbook
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+
+ wb = Workbook()
+ ws = wb.active
+
+ #Row/Col management
+ ws.insert_rows(fdp.ConsumeInt(100))
+ ws.insert_cols(fdp.ConsumeInt(100))
+ ws.delete_rows(fdp.ConsumeInt(100),fdp.ConsumeInt(100))
+ ws.delete_cols(fdp.ConsumeInt(100),fdp.ConsumeInt(100))
+ ws.column_dimensions.group(
+ chr(fdp.ConsumeIntInRange(65,90)),
+ chr(fdp.ConsumeIntInRange(65,90)),
+ hidden=True
+ )
+ ws.row_dimensions.group(
+ fdp.ConsumeInt(100),
+ fdp.ConsumeInt(100),
+ hidden=True
+ )
+
+ #Cell management
+ ws['A1'] = datetime.datetime(2022, 1, 1)
+ format = ws['A1'].number_format
+
+ ws.move_range(
+ "G4:H10",
+ rows=fdp.ConsumeInt(100),
+ cols=fdp.ConsumeInt(100),
+ translate=fdp.ConsumeBool()
+ )
+
+ try:
+ sr = fdp.ConsumeInt(100)
+ sc = fdp.ConsumeInt(100)
+ er = fdp.ConsumeInt(100)
+ ec = fdp.ConsumeInt(100)
+ ws.merge_cells(start_row=sr, start_column=sc, end_row=er, end_column=ec)
+ ws.unmerge_cells(start_row=sr, start_column=sc, end_row=er, end_column=ec)
+ except ValueError as e:
+ if "Min value is 1" not in str(e):
+ raise e
+
+
+ wb.save('%s.xlsx'%fdp.ConsumeString(10))
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/fuzz_sort.py b/projects/openpyxl/fuzz_sort.py
new file mode 100644
index 00000000..b3b5d800
--- /dev/null
+++ b/projects/openpyxl/fuzz_sort.py
@@ -0,0 +1,42 @@
+#!/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.
+
+import atheris
+import sys
+with atheris.instrument_imports():
+ from openpyxl import Workbook
+
+def TestInput(data):
+ fdp = atheris.FuzzedDataProvider(data)
+
+ wb = Workbook()
+ ws = wb.active
+
+ ws.append(['Col1', 'Col2'])
+ for i in range(2,20):
+ ws.append([fdp.ConsumeIntInRange(1,100),fdp.ConsumeIntInRange(1,100)])
+
+ ws.auto_filter.ref = "A%d:B%d"%(fdp.ConsumeInt(10),fdp.ConsumeInt(10))
+ ws.auto_filter.add_filter_column(0, [fdp.ConsumeInt(10),fdp.ConsumeInt(10)])
+ ws.auto_filter.add_sort_condition("B%d:B%d"%(fdp.ConsumeInt(10),fdp.ConsumeInt(10)))
+
+ wb.save('%s.xlsx'%fdp.ConsumeString(10))
+
+def main():
+ atheris.Setup(sys.argv, TestInput, enable_python_coverage=True)
+ atheris.Fuzz()
+
+if __name__ == "__main__":
+ main()
diff --git a/projects/openpyxl/project.yaml b/projects/openpyxl/project.yaml
new file mode 100644
index 00000000..ef3d74ae
--- /dev/null
+++ b/projects/openpyxl/project.yaml
@@ -0,0 +1,13 @@
+fuzzing_engines:
+- libfuzzer
+homepage: https://foss.heptapod.net/openpyxl/openpyxl
+language: python
+main_repo: https://foss.heptapod.net/openpyxl/openpyxl
+primary_contact: "charlie.clark@clark-consulting.eu"
+sanitizers:
+- address
+- undefined
+vendor_ccs:
+- david@adalogics.com
+- adam@adalogics.com
+- arthur.chan@adalogics.com