Skip to content

Commit

Permalink
Refactor the inline Python commands into a Python binary.
Browse files Browse the repository at this point in the history
This is needed when `python3` does not exist in the runtime environment.
  • Loading branch information
xinhaoyuan committed Oct 6, 2021
1 parent 4bafba5 commit 3b8fcbe
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 9 deletions.
10 changes: 10 additions & 0 deletions fuzzing/engines/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ cc_fuzzing_engine(
name = "libfuzzer",
display_name = "libFuzzer",
launcher = "libfuzzer_launcher.sh",
launcher_data = {
"//fuzzing/tools:realpath": "REALPATH_PATH",
},
library = ":libfuzzer_stub",
visibility = ["//visibility:public"],
)
Expand All @@ -46,6 +49,7 @@ cc_fuzzing_engine(
launcher = "honggfuzz_launcher.sh",
launcher_data = {
"@honggfuzz//:honggfuzz": "HONGGFUZZ_PATH",
"//fuzzing/tools:realpath": "REALPATH_PATH",
},
library = "@honggfuzz//:honggfuzz_engine",
visibility = ["//visibility:public"],
Expand All @@ -58,6 +62,9 @@ cc_fuzzing_engine(
name = "replay",
display_name = "Replay",
launcher = "replay_launcher.sh",
launcher_data = {
"//fuzzing/tools:realpath": "REALPATH_PATH",
},
library = "//fuzzing/replay:replay_main",
visibility = ["//visibility:public"],
)
Expand All @@ -69,6 +76,9 @@ java_fuzzing_engine(
name = "jazzer",
display_name = "Jazzer",
launcher = "jazzer_launcher.sh",
launcher_data = {
"//fuzzing/tools:realpath": "REALPATH_PATH",
},
library = "@jazzer//agent:jazzer_api_compile_only",
visibility = ["//visibility:public"],
)
9 changes: 6 additions & 3 deletions fuzzing/private/engine.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ def _make_fuzzing_engine_info(ctx):
if data_env_var:
if data_env_var in env_vars:
fail("Multiple data dependencies map to variable '%s'." % data_env_var)
if len(data_files) != 1:
fail("Data dependency for variable '%s' doesn't map to exactly one file." % data_env_var)
env_vars[data_env_var] = data_files[0]
if len(data_files) == 1:
env_vars[data_env_var] = data_files[0]
elif data_label.files_to_run.executable:
env_vars[data_env_var] = data_label.files_to_run.executable
else:
fail("Data dependency for variable '%s' is not a single file or executable." % data_env_var)
launcher_runfiles = launcher_runfiles.merge(ctx.runfiles(files = data_files))
launcher_runfiles = launcher_runfiles.merge(data_label[DefaultInfo].default_runfiles)

Expand Down
22 changes: 16 additions & 6 deletions fuzzing/private/java_utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,18 @@ source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/
# Export the env variables required for subprocesses to find their runfiles.
runfiles_export_envvars
"""

script_format_part = """
# Determine the path to load libjvm.so from, either relative to the location of
# the java binary or to $JAVA_HOME, if set. On OSS-Fuzz, the path is provided in
# JVM_LD_LIBRARY_PATH.
JAVA_BIN=$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$(which java)")
JAVA_HOME=${JAVA_HOME:-${JAVA_BIN%/bin/java}}
JAVA_BIN=$("$(rlocation {realpath})" "$(which java)")
JAVA_HOME=${{JAVA_HOME:-${{JAVA_BIN%/bin/java}}}}
# The location of libjvm.so relative to the JDK differs between JDK <= 8 and 9+.
JVM_LD_LIBRARY_PATH=${JVM_LD_LIBRARY_PATH:-"$JAVA_HOME/lib/server:$JAVA_HOME/lib/amd64/server"}
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$JVM_LD_LIBRARY_PATH
"""
JVM_LD_LIBRARY_PATH=${{JVM_LD_LIBRARY_PATH:-"$JAVA_HOME/lib/server:$JAVA_HOME/lib/amd64/server"}}
export LD_LIBRARY_PATH=${{LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}}$JVM_LD_LIBRARY_PATH
script_format_part = """
source "$(rlocation {sanitizer_options})"
exec "$(rlocation {driver})" \
--agent_path="$(rlocation {agent})" \
Expand All @@ -136,6 +136,7 @@ exec "$(rlocation {driver})" \
deploy_jar = runfile_path(ctx, ctx.file.target_deploy_jar),
driver = runfile_path(ctx, driver),
native_dirs = ":".join(native_dirs),
realpath = runfile_path(ctx, ctx.executable._realpath),
sanitizer_options = runfile_path(ctx, ctx.file.sanitizer_options),
)
ctx.actions.write(script, script_content, is_executable = True)
Expand Down Expand Up @@ -232,6 +233,9 @@ def _jazzer_fuzz_binary_impl(ctx):

runfiles = runfiles.merge(ctx.runfiles([ctx.file.sanitizer_options]))

runfiles = runfiles.merge(ctx.runfiles([ctx.executable._realpath]))
runfiles = runfiles.merge(ctx.attr._realpath[DefaultInfo].default_runfiles)

script = _jazzer_fuzz_binary_script(ctx, native_libs, driver)
return [DefaultInfo(executable = script, runfiles = runfiles)]

Expand Down Expand Up @@ -283,6 +287,12 @@ Rule that creates a binary that invokes Jazzer on the specified target.
allow_single_file = [".jar"],
mandatory = True,
),
"_realpath": attr.label(
doc = "The realpath util needed by the binary script.",
default = "//fuzzing/tools:realpath",
executable = True,
cfg = "target",
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
Expand Down
7 changes: 7 additions & 0 deletions fuzzing/tools/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ py_binary(
deps = [requirement("absl-py")],
)

py_binary(
name = "realpath",
srcs = ["realpath.py"],
python_version = "PY3",
visibility = ["//visibility:public"],
)

py_binary(
name = "validate_dict",
srcs = ["validate_dict.py"],
Expand Down
27 changes: 27 additions & 0 deletions fuzzing/tools/realpath.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2020 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
#
# https://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.

# Lint as: python3
"""
Gets the realpath of a input path.
This is a portable replacement of the `readlink -f/realpath`.
"""

import os, sys

if len(sys.argv) < 2:
print("Need an argument for the input path.", file=sys.stderr)
sys.exit(1)
print(os.path.realpath(sys.argv[1]))

0 comments on commit 3b8fcbe

Please sign in to comment.