/* * Copyright 2014-present Facebook, Inc. * * 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. */ package com.facebook.buck.cxx; import com.facebook.buck.io.FileContentsScrubber; import com.facebook.buck.io.FileScrubber; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; public class FileContentsScrubberOverflowTest { private static class FakeFileChannel extends FileChannel { private final AtomicBoolean unread = new AtomicBoolean(true); // Ten digits to match size metadata. Doesn't fit in 32-bits. public static final long FILE_SIZE = 6000000000L; // From ObjectFileScrubbers. public static final int ENTRY_SIZE = 16 + 12 + 6 + 6 + 8 + 10 + 2; // Pretend to read out an object file's metadata. @Override public int read(ByteBuffer buf) { // Scrubber is trying to read the global header, do nothing. if (unread.getAndSet(false)) { buf.put(ObjectFileScrubbers.GLOBAL_HEADER); return buf.capacity(); } // None of these values matter except for size and magic. byte[] filename = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; byte[] mtime = Arrays.copyOf(filename, 12); byte[] owner = Arrays.copyOf(filename, 6); byte[] group = Arrays.copyOf(filename, 6); byte[] mode = Arrays.copyOf(filename, 8); // Half so scrubber thinks there are two entries. That way it'll have to do math to update // its position (and we want to see if it overflows). byte[] size = new byte[] { '3', '0', '0', '0', '0', '0', '0', '0', '0', '0', }; byte[] magic = ObjectFileScrubbers.END_OF_FILE_HEADER_MARKER; buf.put(filename); buf.put(mtime); buf.put(owner); buf.put(group); buf.put(mode); buf.put(size); buf.put(magic); return ENTRY_SIZE; } @Override public int write(ByteBuffer buf) { return ENTRY_SIZE; } @Override public FileChannel position(long newPosition) { return this; } @Override public long size() { return FILE_SIZE; } /* Unused. */ @Override public void force(boolean metaData) { throw new UnsupportedOperationException(); } @Override protected void implCloseChannel() throws IOException { throw new UnsupportedOperationException(); } @Override public FileLock lock(long position, long size, boolean shared) { throw new UnsupportedOperationException(); } @Override public MappedByteBuffer map(FileChannel.MapMode mode, long position, long size) { throw new UnsupportedOperationException(); } @Override public long read(ByteBuffer[] dsts, int offset, int length) { throw new UnsupportedOperationException(); } @Override public int read(ByteBuffer dst, long position) { throw new UnsupportedOperationException(); } @Override public long position() { throw new UnsupportedOperationException(); } @Override public long transferFrom(ReadableByteChannel src, long position, long count) { throw new UnsupportedOperationException(); } @Override public long transferTo(long position, long count, WritableByteChannel target) { throw new UnsupportedOperationException(); } @Override public FileLock tryLock(long position, long size, boolean shared) { throw new UnsupportedOperationException(); } @Override public long write(ByteBuffer[] srcs, int offset, int length) { throw new UnsupportedOperationException(); } @Override public int write(ByteBuffer src, long position) { throw new UnsupportedOperationException(); } @Override public FileChannel truncate(long size) { throw new UnsupportedOperationException(); } } @Test public void thatFileSizesOver32BitsIsOkay() throws IOException, FileScrubber.ScrubException { FileContentsScrubber scrubber = ObjectFileScrubbers.createDateUidGidScrubber(ObjectFileScrubbers.PaddingStyle.LEFT); scrubber.scrubFile(new FakeFileChannel()); } }