@@ -3598,6 +3598,122 @@ EOF
35983598 [[ -f " $output_base /external/+repo+foo/ruff" ]] || fail " Expected ruff binary to be extracted"
35993599}
36003600
3601+ # Verifies that files without user-readable permissions in archives are made
3602+ # readable after extraction.
3603+ function test_extract_non_readable_file_tar() {
3604+ local archive_tar=" ${TEST_TMPDIR} /non_readable.tar.gz"
3605+
3606+ python3 -c "
3607+ import tarfile
3608+ import io
3609+ import gzip
3610+
3611+ content = b'secret content'
3612+ with gzip.open('${archive_tar} ', 'wb') as gz:
3613+ with tarfile.open(fileobj=gz, mode='w') as tar:
3614+ info = tarfile.TarInfo(name='non_readable_dir/non_readable.txt')
3615+ info.size = len(content)
3616+ info.mode = 0o000 # No permissions
3617+ tar.addfile(info, io.BytesIO(content))
3618+ "
3619+
3620+ cat > $( setup_module_dot_bazel) << EOF
3621+ repo = use_repo_rule('//:test.bzl', 'repo')
3622+ repo(name = 'foo')
3623+ EOF
3624+ touch BUILD
3625+
3626+ cat > test.bzl << EOF
3627+ def _impl(repository_ctx):
3628+ repository_ctx.extract('${archive_tar} ', 'out_dir')
3629+ # Verify the file is readable by reading it
3630+ content = repository_ctx.read('out_dir/non_readable_dir/non_readable.txt')
3631+ if 'secret content' not in content:
3632+ fail('Expected to read file content, got: ' + content)
3633+ repository_ctx.file("BUILD", "filegroup(name='bar', srcs=[])")
3634+
3635+ repo = repository_rule(implementation=_impl)
3636+ EOF
3637+
3638+ bazel build @foo//:bar >& $TEST_log || fail " Failed to build"
3639+ }
3640+
3641+ function test_extract_non_readable_file_zip() {
3642+ local archive_zip=" ${TEST_TMPDIR} /non_readable.zip"
3643+
3644+ pushd " ${TEST_TMPDIR} "
3645+ mkdir -p non_readable_zip_dir
3646+ echo " secret zip content" > non_readable_zip_dir/non_readable.txt
3647+ python3 -c "
3648+ import zipfile
3649+ import os
3650+ with zipfile.ZipFile('non_readable.zip', 'w') as zf:
3651+ info = zipfile.ZipInfo('non_readable_zip_dir/non_readable.txt')
3652+ info.external_attr = 0o000 << 16 # No permissions
3653+ zf.writestr(info, 'secret zip content')
3654+ "
3655+ popd
3656+
3657+ cat > $( setup_module_dot_bazel) << EOF
3658+ repo = use_repo_rule('//:test.bzl', 'repo')
3659+ repo(name = 'foo')
3660+ EOF
3661+ touch BUILD
3662+
3663+ cat > test.bzl << EOF
3664+ def _impl(repository_ctx):
3665+ repository_ctx.extract('${archive_zip} ', 'out_dir')
3666+ # Verify the file is readable by reading it
3667+ content = repository_ctx.read('out_dir/non_readable_zip_dir/non_readable.txt')
3668+ if 'secret zip content' not in content:
3669+ fail('Expected to read file content, got: ' + content)
3670+ repository_ctx.file("BUILD", "filegroup(name='bar', srcs=[])")
3671+
3672+ repo = repository_rule(implementation=_impl)
3673+ EOF
3674+
3675+ bazel build @foo//:bar >& $TEST_log || fail " Failed to build"
3676+ }
3677+
3678+ function test_extract_non_readable_file_ar() {
3679+ local archive_ar=" ${TEST_TMPDIR} /non_readable.ar"
3680+
3681+ # Create a valid AR file, then patch the permission field to 0000
3682+ pushd " ${TEST_TMPDIR} "
3683+ echo " secret ar content" > non_readable.txt
3684+ ar rc non_readable.ar non_readable.txt
3685+ # Patch the mode field (bytes 40-47 after the 8-byte magic) to "0 "
3686+ python3 -c "
3687+ with open('non_readable.ar', 'r+b') as f:
3688+ # AR magic is 8 bytes, then header starts
3689+ # Header format: filename(16) + mtime(12) + owner(6) + group(6) + mode(8) + size(10) + magic(2)
3690+ # Mode is at offset 8 + 16 + 12 + 6 + 6 = 48
3691+ f.seek(48)
3692+ f.write(b'0 ') # 8 bytes for mode 0000 in octal
3693+ "
3694+ popd
3695+
3696+ cat > $( setup_module_dot_bazel) << EOF
3697+ repo = use_repo_rule('//:test.bzl', 'repo')
3698+ repo(name = 'foo')
3699+ EOF
3700+ touch BUILD
3701+
3702+ cat > test.bzl << EOF
3703+ def _impl(repository_ctx):
3704+ repository_ctx.extract('${archive_ar} ', 'out_dir')
3705+ # Verify the file is readable by reading it
3706+ content = repository_ctx.read('out_dir/non_readable.txt')
3707+ if 'secret ar content' not in content:
3708+ fail('Expected to read file content, got: ' + content)
3709+ repository_ctx.file("BUILD", "filegroup(name='bar', srcs=[])")
3710+
3711+ repo = repository_rule(implementation=_impl)
3712+ EOF
3713+
3714+ bazel build @foo//:bar >& $TEST_log || fail " Failed to build"
3715+ }
3716+
36013717# Regression test for https://github.com/bazelbuild/bazel/issues/27446.
36023718function do_test_local_module_file_patch() {
36033719 cat > $( setup_module_dot_bazel) << 'EOF '
0 commit comments