diff --git a/projects/closure-library/Dockerfile b/projects/closure-library/Dockerfile new file mode 100644 index 000000000..c68e04e9c --- /dev/null +++ b/projects/closure-library/Dockerfile @@ -0,0 +1,25 @@ +# Copyright 2023 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-javascript + +COPY build.sh $SRC/ + +RUN git clone --depth 1 https://github.com/google/closure-library.git + +COPY fuzz.js $SRC/closure-library + +WORKDIR $SRC/closure-library diff --git a/projects/closure-library/build.sh b/projects/closure-library/build.sh new file mode 100644 index 000000000..7a2b5adde --- /dev/null +++ b/projects/closure-library/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash -eu +# Copyright 2023 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. +# +################################################################################ + +# Install dependencies. +npm install +npm install --save-dev @jazzer.js/core + +# Build Fuzzers. +compile_javascript_fuzzer closure-library fuzz.js -i closure-library --sync diff --git a/projects/closure-library/fuzz.js b/projects/closure-library/fuzz.js new file mode 100644 index 000000000..9e7dbcbb7 --- /dev/null +++ b/projects/closure-library/fuzz.js @@ -0,0 +1,74 @@ +// Copyright 2023 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. +// +//////////////////////////////////////////////////////////////////////////////// + +const { FuzzedDataProvider } = require('@jazzer.js/core'); +require("google-closure-library"); +const SafeHtml = goog.require('goog.html.SafeHtml'); +const googString = goog.require('goog.string.Const'); +const TrustedResourceUrl = goog.require('goog.html.TrustedResourceUrl'); +const UncheckedResourceUrl = goog.require('goog.html.UncheckedResourceUrl'); + +module.exports.fuzz = function(data) { + const provider = new FuzzedDataProvider(data); + + const html = provider.consumeString(300); + const shouldWrap = provider.consumeBoolean(); + const tagName = shouldWrap ? provider.consumeString(10) : ''; + + let safeHtml; + try { + const method = provider.consumeIntegralInRange(1, 6); + + switch (method) { + case 1: + safeHtml = SafeHtml.create(tagName, { innerHtml: html }); + break; + case 2: + safeHtml = SafeHtml.fromConstant(googString.from(html)); + break; + case 3: + safeHtml = SafeHtml.fromTrustedResourceUrl(TrustedResourceUrl.fromConstant(googString.from(html))); + break; + case 4: + safeHtml = SafeHtml.fromUntrustedResourceUrl(UncheckedResourceUrl.fromConstant(googString.from(html))); + break; + case 5: + safeHtml = SafeHtml.unwrap(SafeHtml.create(tagName, { innerHtml: html })); + break; + case 6: + safeHtml = SafeHtml.concat(SafeHtml.create(tagName, { innerHtml: html }), SafeHtml.EMPTY); + break; + } + + const htmlString = SafeHtml.unwrap(safeHtml); + const isEmpty = provider.consumeBoolean(); + const emptySafeHtml = isEmpty ? SafeHtml.EMPTY : safeHtml; + const concatenatedSafeHtml = SafeHtml.concat(safeHtml, emptySafeHtml); + const isTrusted = provider.consumeBoolean(); + const trustedSafeHtml = isTrusted ? SafeHtml.htmlEscape(htmlString) : concatenatedSafeHtml; + SafeHtml.unwrap(trustedSafeHtml); + } catch (error) { + if (!ignoredError(error)) throw error; + } +}; + +function ignoredError(error) { + return !!ignored.find((message) => error.message.indexOf(message) !== -1); +} + +const ignored = [ + "Cannot read properties of" +]; diff --git a/projects/closure-library/project.yaml b/projects/closure-library/project.yaml new file mode 100644 index 000000000..ba4dcc6dc --- /dev/null +++ b/projects/closure-library/project.yaml @@ -0,0 +1,15 @@ +homepage: https://developers.google.com/closure/library/ +language: javascript +main_repo: https://github.com/google/closure-library +fuzzing_engines: +- libfuzzer +sanitizers: +- none +vendor_ccs: + - "wagner@code-intelligence.com" + - "yakdan@code-intelligence.com" + - "glendowne@code-intelligence.com" + - "patrice.salathe@code-intelligence.com" + - "hlin@code-intelligence.com" + - "christopher.krah@code-intelligence.com" + - "bug-disclosure@code-intelligence.com"