Get Python3 interpreter path reliably by using the same Python3 runtime as for Bazel.

Not changing the one used in jazzer binary script since the new runtime is only available when running with Bazel, but the binary script may be packaged to OSS-fuzz.
diff --git a/fuzzing/engines/honggfuzz_launcher.sh b/fuzzing/engines/honggfuzz_launcher.sh
index 9c0bf62..32ab77b 100755
--- a/fuzzing/engines/honggfuzz_launcher.sh
+++ b/fuzzing/engines/honggfuzz_launcher.sh
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-command_line="$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${HONGGFUZZ_PATH})"
+command_line="$("${PYTHON3_INTERPRETER}" -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${HONGGFUZZ_PATH})"
 command_line+=("--workspace=${FUZZER_OUTPUT_ROOT}")
 
 if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
diff --git a/fuzzing/engines/jazzer_launcher.sh b/fuzzing/engines/jazzer_launcher.sh
index c1601e5..a450223 100755
--- a/fuzzing/engines/jazzer_launcher.sh
+++ b/fuzzing/engines/jazzer_launcher.sh
@@ -16,7 +16,7 @@
 # engine. The launch configuration is supplied by the launcher script through
 # environment variables.
 
-command_line=("$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
+command_line=("$("${PYTHON3_INTERPRETER}" -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
 
 # libFuzzer flags (compatible with Jazzer).
 
diff --git a/fuzzing/engines/libfuzzer_launcher.sh b/fuzzing/engines/libfuzzer_launcher.sh
index 6346db8..06efa55 100755
--- a/fuzzing/engines/libfuzzer_launcher.sh
+++ b/fuzzing/engines/libfuzzer_launcher.sh
@@ -16,7 +16,7 @@
 # libFuzzer engine. The launch configuration is supplied by the launcher
 # script through environment variables.
 
-command_line=("$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
+command_line=("$("${PYTHON3_INTERPRETER}" -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
 
 # libFuzzer flags.
 
diff --git a/fuzzing/engines/replay_launcher.sh b/fuzzing/engines/replay_launcher.sh
index 4ebf293..8e1dadf 100755
--- a/fuzzing/engines/replay_launcher.sh
+++ b/fuzzing/engines/replay_launcher.sh
@@ -16,7 +16,7 @@
     echo "NOTE: Non-regression mode is not supported by the replay engine."
 fi
 
-command_line=("$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
+command_line=("$("${PYTHON3_INTERPRETER}" -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
 if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
     command_line+=("${FUZZER_SEED_CORPUS_DIR}")
 fi
diff --git a/fuzzing/private/common.bzl b/fuzzing/private/common.bzl
index 18a4f29..d81e80a 100644
--- a/fuzzing/private/common.bzl
+++ b/fuzzing/private/common.bzl
@@ -16,12 +16,13 @@
 
 load("//fuzzing/private:binary.bzl", "FuzzingBinaryInfo")
 
-def _fuzzing_launcher_script(ctx):
+def _fuzzing_launcher_script(ctx, python3_interpreter_path):
     binary_info = ctx.attr.binary[FuzzingBinaryInfo]
     script = ctx.actions.declare_file(ctx.label.name)
 
     script_template = """
-{environment}
+export PYTHON3_INTERPRETER='{python3_interpreter_path}'
+{launcher_environment}
 echo "Launching {binary_path} as a {engine_name} fuzz test..."
 RUNFILES_DIR="$0.runfiles" \
 exec "{launcher}" \
@@ -32,7 +33,8 @@
     "$@"
 """
     script_content = script_template.format(
-        environment = "\n".join([
+        python3_interpreter_path = python3_interpreter_path,
+        launcher_environment = "\n".join([
             "export %s='%s'" % (var, file.short_path)
             for var, file in binary_info.engine_info.launcher_environment.items()
         ]),
@@ -47,13 +49,22 @@
     return script
 
 def _fuzzing_launcher_impl(ctx):
-    script = _fuzzing_launcher_script(ctx)
-
     binary_info = ctx.attr.binary[FuzzingBinaryInfo]
     runfiles = ctx.runfiles()
     runfiles = runfiles.merge(binary_info.engine_info.launcher_runfiles)
     runfiles = runfiles.merge(ctx.attr._launcher[DefaultInfo].default_runfiles)
     runfiles = runfiles.merge(ctx.attr.binary[DefaultInfo].default_runfiles)
+
+    py3_runtime = ctx.toolchains["@rules_python//python:toolchain_type"].py3_runtime
+    if py3_runtime.interpreter:
+        runfiles = runfiles.merge(ctx.runfiles(files = [py3_runtime.interpreter]))
+        runfiles = runfiles.merge(ctx.runfiles(files = py3_runtime.files.to_list()))
+        python3_interpreter_path = py3_runtime.interpreter.short_path
+    else:
+        python3_interpreter_path = py3_runtime.interpreter_path
+
+    script = _fuzzing_launcher_script(ctx, python3_interpreter_path)
+
     return [DefaultInfo(executable = script, runfiles = runfiles)]
 
 fuzzing_launcher = rule(
@@ -76,6 +87,7 @@
             mandatory = True,
         ),
     },
+    toolchains = ["@rules_python//python:toolchain_type"],
     executable = True,
 )
 
diff --git a/fuzzing/private/engine.bzl b/fuzzing/private/engine.bzl
index 9d8656d..15ba13a 100644
--- a/fuzzing/private/engine.bzl
+++ b/fuzzing/private/engine.bzl
@@ -32,6 +32,7 @@
 
     launcher_runfiles = ctx.runfiles(files = [ctx.file.launcher])
     env_vars = {}
+
     for data_label, data_env_var in ctx.attr.launcher_data.items():
         data_files = data_label.files.to_list()
         if data_env_var:
diff --git a/fuzzing/private/regression.bzl b/fuzzing/private/regression.bzl
index 104993d..a46ae16 100644
--- a/fuzzing/private/regression.bzl
+++ b/fuzzing/private/regression.bzl
@@ -25,6 +25,7 @@
 export FUZZER_BINARY='{fuzzer_binary}'
 export FUZZER_SEED_CORPUS_DIR='{seed_corpus_dir}'
 export FUZZER_IS_REGRESSION=1
+export PYTHON3_INTERPRETER='{python3_interpreter_path}'
 {engine_launcher_environment}
 
 mkdir -p "$FUZZER_OUTPUT_CORPUS_DIR"
@@ -32,9 +33,22 @@
 
 exec '{engine_launcher}'
 """
+    runfiles = ctx.runfiles()
+    runfiles = runfiles.merge(ctx.attr.binary[DefaultInfo].default_runfiles)
+    runfiles = runfiles.merge(binary_info.engine_info.launcher_runfiles)
+
+    py3_runtime = ctx.toolchains["@rules_python//python:toolchain_type"].py3_runtime
+    if py3_runtime.interpreter:
+        runfiles = runfiles.merge(ctx.runfiles(files = [py3_runtime.interpreter]))
+        runfiles = runfiles.merge(ctx.runfiles(files = py3_runtime.files.to_list()))
+        python3_interpreter_path = py3_runtime.interpreter.short_path
+    else:
+        python3_interpreter_path = py3_runtime.interpreter_path
+
     script_content = script_template.format(
         fuzzer_binary = ctx.executable.binary.short_path,
         seed_corpus_dir = binary_info.corpus_dir.short_path,
+        python3_interpreter_path = python3_interpreter_path,
         engine_launcher_environment = "\n".join([
             "export %s='%s'" % (var, file.short_path)
             for var, file in binary_info.engine_info.launcher_environment.items()
@@ -42,10 +56,6 @@
         engine_launcher = binary_info.engine_info.launcher.short_path,
     )
     ctx.actions.write(script, script_content, is_executable = True)
-
-    runfiles = ctx.runfiles()
-    runfiles = runfiles.merge(ctx.attr.binary[DefaultInfo].default_runfiles)
-    runfiles = runfiles.merge(binary_info.engine_info.launcher_runfiles)
     return [DefaultInfo(executable = script, runfiles = runfiles)]
 
 fuzzing_regression_test = rule(
@@ -62,5 +72,6 @@
             mandatory = True,
         ),
     },
+    toolchains = ["@rules_python//python:toolchain_type"],
     test = True,
 )