[vm] Fix obfuscation of uri
https://github.com/flutter/flutter/issues/99477
https://github.com/dart-lang/sdk/issues/44215
TEST=Test was added.
Change-Id: I585da436f9692d7f2e08db7f74c1a71ad09a1cb1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/236220
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
diff --git a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
index 6b5f9b2..762b17e 100644
--- a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
+++ b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
@@ -37,9 +37,16 @@
metadata.protectedNames.add(name + "=");
}
final parent = node.parent;
+ final Library library;
if (parent is Class) {
metadata.protectedNames.add(parent.name);
+ library = parent.enclosingLibrary;
+ } else if (parent is Library) {
+ library = parent;
+ } else {
+ throw "Unexpected parent";
}
+ metadata.protectedNames.add(library.importUri.toString());
break;
}
}
diff --git a/pkg/vm/test/obfuscation_test.dart b/pkg/vm/test/obfuscation_test.dart
new file mode 100644
index 0000000..8ee7401
--- /dev/null
+++ b/pkg/vm/test/obfuscation_test.dart
@@ -0,0 +1,188 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import "dart:io";
+
+import 'package:front_end/src/api_unstable/vm.dart'
+ show computePlatformBinariesLocation;
+
+main() {
+ final Directory tmpDir =
+ Directory.systemTemp.createTempSync("obfuscationtest");
+ try {
+ final Uri tmpDirUri = tmpDir.uri;
+ final Uri secretfilename = tmpDirUri.resolve("secretfilename.dart");
+ final File secretfilenameFile = new File.fromUri(secretfilename);
+ secretfilenameFile.writeAsStringSync("""
+import "secretfilename2.dart";
+
+main() {
+ print("Hello, World!");
+ verySecretFoo();
+}
+""");
+ final Uri secretfilename2 = tmpDirUri.resolve("secretfilename2.dart");
+ final File secretfilename2File = new File.fromUri(secretfilename2);
+ secretfilename2File.writeAsStringSync("""
+@pragma('vm:entry-point')
+void verySecretFoo() {
+ print("foo!");
+ alsoVerySecretFoo();
+}
+
+void alsoVerySecretFoo() {
+ print("foo too!");
+}
+""");
+
+ List<MappingPair> mapping = getSnapshotMap(tmpDir, secretfilenameFile);
+ bool good = verify(mapping, {
+ // This contains @pragma('vm:entry-point') and the uri should not change.
+ secretfilename2.toString(),
+ // This contains @pragma('vm:entry-point') and the name should not change.
+ "verySecretFoo",
+ }, {
+ // This is not special and should have been obfuscated.
+ secretfilename.toString(),
+ // This is not special and should have been obfuscated.
+ "alsoVerySecretFoo"
+ });
+ if (!good) throw "Obfuscation didn't work as expected";
+ print("Good");
+ } finally {
+ tmpDir.deleteSync(recursive: true);
+ }
+}
+
+List<MappingPair> getSnapshotMap(Directory tmpDir, File compileDartFile) {
+ final Uri genKernel = Platform.script.resolve('../bin/gen_kernel.dart');
+ final File genKernelFile = new File.fromUri(genKernel);
+ if (!genKernelFile.existsSync()) {
+ throw "Didn't find gen_kernel at $genKernel";
+ }
+
+ File resolvedExecutableFile = new File(Platform.resolvedExecutable);
+ Uri resolvedExecutable = resolvedExecutableFile.uri;
+ String genSnapshotFilename = "gen_snapshot";
+ if (Platform.isWindows) genSnapshotFilename += ".exe";
+
+ Uri genSnapshot = resolvedExecutable.resolve(genSnapshotFilename);
+ File genSnapshotFile = new File.fromUri(genSnapshot);
+ if (!genSnapshotFile.existsSync()) {
+ print(
+ "Didn't find gen_kernel at $genSnapshot... Trying utils/$genSnapshotFilename");
+ genSnapshot = resolvedExecutable.resolve("utils/$genSnapshotFilename");
+ genSnapshotFile = new File.fromUri(genSnapshot);
+ if (!genSnapshotFile.existsSync()) {
+ throw "Didn't find gen_kernel at $genSnapshot";
+ }
+ }
+
+ final Uri platformDill = computePlatformBinariesLocation()
+ .resolve('vm_platform_strong_product.dill');
+ final File platformDillFile = new File.fromUri(platformDill);
+ if (!platformDillFile.existsSync()) {
+ throw "Didn't find vm_platform_strong_product at $platformDill";
+ }
+
+ final Uri tmpDirUri = tmpDir.uri;
+
+ final Uri kernelDill = tmpDirUri.resolve("kernel.dill");
+ final File kernelDillFile = new File.fromUri(kernelDill);
+
+ print("Running gen_kernel");
+ // Extracted from pkg/dart2native/lib/dart2native.dart.
+ final ProcessResult kernelRun = Process.runSync(Platform.resolvedExecutable, [
+ genKernelFile.path,
+ "--platform",
+ platformDillFile.path,
+ "--aot",
+ "-Ddart.vm.product=true",
+ "-o",
+ kernelDillFile.path,
+ "--invocation-modes=compile",
+ "--verbosity=all",
+ compileDartFile.path
+ ]);
+
+ if (kernelRun.exitCode != 0) {
+ throw "Got exit code ${kernelRun.exitCode}\n"
+ "stdout: ${kernelRun.stdout}\n"
+ "stderr: ${kernelRun.stderr}";
+ }
+
+ final Uri aotElf = tmpDirUri.resolve("aot.elf");
+ final File aotElfFile = new File.fromUri(aotElf);
+ final Uri obfuscationMap = tmpDirUri.resolve("obfuscation.map");
+ final File obfuscationMapFile = new File.fromUri(obfuscationMap);
+
+ print("Running $genSnapshot");
+ // Extracted from pkg/dart2native/lib/dart2native.dart.
+ final ProcessResult snapshotRun = Process.runSync(genSnapshotFile.path, [
+ "--snapshot-kind=app-aot-elf",
+ "--elf=${aotElfFile.path}",
+ "--dwarf-stack-traces",
+ "--obfuscate",
+ "--strip",
+ "--save-obfuscation-map=${obfuscationMapFile.path}",
+ kernelDillFile.path,
+ ]);
+
+ if (snapshotRun.exitCode != 0) {
+ throw "Got exit code ${snapshotRun.exitCode}\n"
+ "stdout: ${snapshotRun.stdout}\n"
+ "stderr: ${snapshotRun.stderr}";
+ }
+
+ print("Reading $obfuscationMap");
+
+ return readJsonMapping(obfuscationMapFile);
+}
+
+List<MappingPair> readJsonMapping(File file) {
+ List<MappingPair> result = [];
+ List<dynamic> json = jsonDecode(file.readAsStringSync());
+ for (int i = 0; i < json.length; i += 2) {
+ result.add(new MappingPair(json[i] as String, json[i + 1] as String));
+ }
+ return result;
+}
+
+class MappingPair {
+ final String from;
+ final String to;
+
+ MappingPair(this.from, this.to);
+
+ String toString() => "MappingPair[$from->$to]";
+}
+
+bool verify(List<MappingPair> mapping, Set<String> expectedIdentity,
+ Set<String> expectedDifferent) {
+ bool good = true;
+ Set<String> missingKeys = new Set<String>.of(expectedIdentity)
+ ..addAll(expectedDifferent);
+ for (MappingPair entry in mapping) {
+ missingKeys.remove(entry.from);
+ if (expectedIdentity.contains(entry.from) && entry.from != entry.to) {
+ print("Expected ${entry.from} to map to itself, "
+ "but mapped to ${entry.to}");
+ good = false;
+ }
+ if (expectedDifferent.contains(entry.from) && entry.from == entry.to) {
+ print("Expected ${entry.from} to map to something different, "
+ "but it didn't.");
+ good = false;
+ }
+ }
+ if (missingKeys.isNotEmpty) {
+ print("Expected to have seen the following entries which wasn't found:");
+ for (String missingKey in missingKeys) {
+ print("- $missingKey");
+ }
+ good = false;
+ }
+ return good;
+}