From baa9f50cb26ffb4be7391ec91b894fce7355b573 Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Tue, 9 Jul 2019 10:09:35 -0700 Subject: [PATCH] Implement range-based pin list This extends the original pin list generation to support specifying a range within a file. If any part of a file is pinned, its local file header in the APK file is pinned as well. Test: Build cuttlefish. Bug: 136040313 Bug: 135953430 Change-Id: I6de8c2b4c2f35c6bf257f61414c6bce761233e51 --- .../src/com/android/signapk/SignApk.java | 66 +++++++++++++------ 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java index 57973ec04..9809ed406 100644 --- a/tools/signapk/src/com/android/signapk/SignApk.java +++ b/tools/signapk/src/com/android/signapk/SignApk.java @@ -381,9 +381,8 @@ class SignApk { byte[] buffer = new byte[4096]; int num; - List pinPatterns = extractPinPatterns(in); + List pinPatterns = extractPinPatterns(in); ArrayList pinByteRanges = pinPatterns == null ? null : new ArrayList<>(); - HashSet namesToPin = new HashSet<>(); ArrayList names = new ArrayList(); for (Enumeration e = in.entries(); e.hasMoreElements();) { @@ -399,13 +398,6 @@ class SignApk { if (Hints.PIN_BYTE_RANGE_ZIP_ENTRY_NAME.equals(entryName)) { continue; // We regenerate it below. } - if (pinPatterns != null) { - for (Pattern pinPattern : pinPatterns) { - if (pinPattern.matcher(entryName).matches()) { - namesToPin.add(entryName); - } - } - } names.add(entryName); } Collections.sort(names); @@ -485,6 +477,7 @@ class SignApk { DataSink entryDataSink = (inspectEntryRequest != null) ? inspectEntryRequest.getDataSink() : null; + long entryDataStart = outCounter.getWrittenBytes(); try (InputStream data = in.getInputStream(inEntry)) { while ((num = data.read(buffer)) > 0) { out.write(buffer, 0, num); @@ -500,11 +493,27 @@ class SignApk { inspectEntryRequest.done(); } - if (namesToPin.contains(name)) { - pinByteRanges.add( - new Hints.ByteRange( - entryHeaderStart, - outCounter.getWrittenBytes())); + if (pinPatterns != null) { + boolean pinFileHeader = false; + for (Hints.PatternWithRange pinPattern : pinPatterns) { + if (!pinPattern.matcher(name).matches()) { + continue; + } + Hints.ByteRange dataRange = + new Hints.ByteRange( + entryDataStart, + outCounter.getWrittenBytes()); + Hints.ByteRange pinRange = + pinPattern.ClampToAbsoluteByteRange(dataRange); + if (pinRange != null) { + pinFileHeader = true; + pinByteRanges.add(pinRange); + } + } + if (pinFileHeader) { + pinByteRanges.add(new Hints.ByteRange(entryHeaderStart, + entryDataStart)); + } } } @@ -528,6 +537,7 @@ class SignApk { DataSink entryDataSink = (inspectEntryRequest != null) ? inspectEntryRequest.getDataSink() : null; + long entryDataStart = outCounter.getWrittenBytes(); InputStream data = in.getInputStream(inEntry); while ((num = data.read(buffer)) > 0) { out.write(buffer, 0, num); @@ -541,11 +551,27 @@ class SignApk { inspectEntryRequest.done(); } - if (namesToPin.contains(name)) { - pinByteRanges.add( - new Hints.ByteRange( - entryHeaderStart, - outCounter.getWrittenBytes())); + if (pinPatterns != null) { + boolean pinFileHeader = false; + for (Hints.PatternWithRange pinPattern : pinPatterns) { + if (!pinPattern.matcher(name).matches()) { + continue; + } + Hints.ByteRange dataRange = + new Hints.ByteRange( + entryDataStart, + outCounter.getWrittenBytes()); + Hints.ByteRange pinRange = + pinPattern.ClampToAbsoluteByteRange(dataRange); + if (pinRange != null) { + pinFileHeader = true; + pinByteRanges.add(pinRange); + } + } + if (pinFileHeader) { + pinByteRanges.add(new Hints.ByteRange(entryHeaderStart, + entryDataStart)); + } } } @@ -558,7 +584,7 @@ class SignApk { } } - private static List extractPinPatterns(JarFile in) throws IOException { + private static List extractPinPatterns(JarFile in) throws IOException { ZipEntry pinMetaEntry = in.getEntry(Hints.PIN_HINT_ASSET_ZIP_ENTRY_NAME); if (pinMetaEntry == null) { return null;