Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Unified Diff: runtime/vm/precompiler.h

Issue 3003583002: [VM, Precompiler] PoC Obfuscator (Closed)
Patch Set: Fix bad refactoring in NewAtomicRename Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.cc ('k') | runtime/vm/precompiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/precompiler.h
diff --git a/runtime/vm/precompiler.h b/runtime/vm/precompiler.h
index 2aff2a4d0cac1f6ef279bce0da3f815b4a4eb876..0acef6e25feb1f566efb1355ba6ac58cb7613b2e 100644
--- a/runtime/vm/precompiler.h
+++ b/runtime/vm/precompiler.h
@@ -398,6 +398,8 @@ class Precompiler : public ValueObject {
void SwitchICCalls();
void ResetPrecompilerState();
+ void Obfuscate();
+
void CollectDynamicFunctionNames();
void PrecompileStaticInitializers();
@@ -476,6 +478,212 @@ class FunctionsTraits {
typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
+#if defined(DART_PRECOMPILER)
+// ObfuscationMap maps Strings to Strings.
+class ObfuscationMapTraits {
+ public:
+ static const char* Name() { return "ObfuscationMapTraits"; }
+ static bool ReportStats() { return false; }
+
+ // Only for non-descriptor lookup and table expansion.
+ static bool IsMatch(const Object& a, const Object& b) {
+ return a.raw() == b.raw();
+ }
+
+ static uword Hash(const Object& key) { return String::Cast(key).Hash(); }
+};
+typedef UnorderedHashMap<ObfuscationMapTraits> ObfuscationMap;
+
+// Obfuscator is a helper class that is responsible for obfuscating
+// identifiers when obfuscation is enabled via isolate flags.
+//
+class Obfuscator : public ValueObject {
+ public:
+ // Create Obfuscator for the given |thread|, with the given |private_key|.
+ // This private key will be used when obfuscating private identifiers
+ // (those starting with '_').
+ //
+ // If obfuscation is enabled constructor will restore obfuscation state
+ // from ObjectStore::obfuscation_map()
+ //
+ // Note: only a single instance of obfuscator should exist at any given
+ // moment on the stack because Obfuscator takes ownership of obfuscation
+ // map. ObjectStore::obfuscation_map() will only be updated when
+ // this Obfuscator is destroyed.
+ Obfuscator(Thread* thread, const String& private_key);
+
+ // If obfuscation is enabled - commit accumulated renames to ObjectStore.
+ ~Obfuscator();
+
+ // If obfuscation is enabled return a rename for the given |name|,
+ // otherwise it is a no-op.
+ //
+ // Note: |name| *must* be a Symbol.
+ //
+ // By default renames are aware about mangling scheme used for private names:
+ // '_ident@key' and '_ident' will be renamed consistently. If such
+ // interpretation is undesirable e.g. it is known that name does not
+ // contain a private key suffix or name is not a Dart identifier at all
+ // then this function should be called with |atomic| set to true.
+ //
+ // Note: if obfuscator was created with private_key then all
+ // renames *must* be atomic.
+ //
+ // This method is guaranteed to return the same value for the same
+ // input and it always preserves leading '_' even for atomic renames.
+ RawString* Rename(const String& name, bool atomic = false) {
+ if (state_ == NULL) {
+ return name.raw();
+ }
+
+ return state_->RenameImpl(name, atomic);
+ }
+
+ // Given a constant |instance| of dart:internal.Symbol rename it by updating
+ // its |name| field.
+ static void ObfuscateSymbolInstance(Thread* thread, const Instance& instance);
+
+ // Given a sequence of obfuscated identifiers deobfuscate it.
+ //
+ // This method is only used by parser when resolving conditional imports
+ // because it needs deobfuscated names to lookup in the environment.
+ //
+ // Note: this operation is not optimized because is very infrequent.
+ static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces);
+
+ // Serialize renaming map as a malloced array of strings.
+ static const char** SerializeMap(Thread* thread);
+
+ private:
+ // Populate renaming map with names that should have identity renaming.
+ // (or in other words: with those names that should not be renamed).
+ void InitializeRenamingMap(Isolate* isolate);
+ void PreventRenaming(Dart_QualifiedFunctionName* entry_points);
+ void PreventRenaming(const char* name);
+ void PreventRenaming(const String& name) { state_->PreventRenaming(name); }
+
+ // ObjectStore::obfuscation_map() is an Array with two elements:
+ // first element is the last used rename and the second element is
+ // renaming map.
+ static const intptr_t kSavedStateNameIndex = 0;
+ static const intptr_t kSavedStateRenamesIndex = 1;
+ static const intptr_t kSavedStateSize = 2;
+
+ static RawArray* GetRenamesFromSavedState(const Array& saved_state) {
+ Array& renames = Array::Handle();
+ renames ^= saved_state.At(kSavedStateRenamesIndex);
+ return renames.raw();
+ }
+
+ static RawString* GetNameFromSavedState(const Array& saved_state) {
+ String& name = String::Handle();
+ name ^= saved_state.At(kSavedStateNameIndex);
+ return name.raw();
+ }
+
+ class ObfuscationState : public ZoneAllocated {
+ public:
+ ObfuscationState(Thread* thread,
+ const Array& saved_state,
+ const String& private_key)
+ : thread_(thread),
+ saved_state_(saved_state),
+ renames_(GetRenamesFromSavedState(saved_state)),
+ private_key_(private_key),
+ string_(String::Handle(thread->zone())),
+ renamed_(String::Handle(thread->zone())) {
+ memset(name_, 0, sizeof(name_));
+
+ // Restore last used rename.
+ string_ = GetNameFromSavedState(saved_state);
+ if (!string_.IsNull()) {
+ string_.ToUTF8(reinterpret_cast<uint8_t*>(name_), sizeof(name_));
+ }
+ }
+
+ void SaveState();
+
+ // Return a rename for the given |name|.
+ //
+ // Note: |name| *must* be a Symbol.
+ //
+ // By default renames are aware about mangling scheme used for private
+ // names: '_ident@key' and '_ident' will be renamed consistently. If such
+ // interpretation is undesirable e.g. it is known that name does not
+ // contain a private key suffix or name is not a Dart identifier at all
+ // then this function should be called with |atomic| set to true.
+ //
+ // Note: if obfuscator was created with private_key then all
+ // renames *must* be atomic.
+ //
+ // This method is guaranteed to return the same value for the same
+ // input.
+ RawString* RenameImpl(const String& name, bool atomic);
+
+ // Register an identity (name -> name) mapping in the renaming map.
+ //
+ // This essentially prevents the given name from being renamed.
+ void PreventRenaming(const String& name);
+ void PreventRenaming(const char* name);
+
+ private:
+ // Build rename for the given |name|.
+ //
+ // For atomic renames BuildRename just returns the next
+ // available rename generated by AtomicRename(...).
+ //
+ // For non-atomic renames BuildRename ensures that private mangled
+ // identifiers (_ident@key) are renamed consistently with non-mangled
+ // counterparts (_ident).
+ RawString* BuildRename(const String& name, bool atomic);
+
+ // Generate a new rename. If |should_be_private| is set to true
+ // then we prefix returned identifier with '_'.
+ RawString* NewAtomicRename(bool should_be_private);
+
+ // Update next_ to generate the next free rename.
+ void NextName();
+
+ Thread* thread_;
+
+ // Saved obfuscation state (ObjectStore::obfuscation_map())
+ const Array& saved_state_;
+
+ // Last used rename. Renames are only using a-zA-Z characters
+ // and are generated in order: a, b, ..., z, A, ..., Z, aa, ba, ...
+ char name_[100];
+
+ ObfuscationMap renames_;
+
+ const String& private_key_;
+
+ // Temporary handles.
+ String& string_;
+ String& renamed_;
+ };
+
+ // Current obfucation state or NULL if obfuscation is not enabled.
+ ObfuscationState* state_;
+};
+#else
+// Minimal do-nothing implementation of an Obfuscator for non-precompiler
+// builds.
+class Obfuscator {
+ public:
+ Obfuscator(Thread* thread, const String& private_key) {}
+ ~Obfuscator() {}
+
+ RawString* Rename(const String& name, bool atomic = false) {
+ return name.raw();
+ }
+
+ static void ObfuscateSymbolInstance(Thread* thread,
+ const Instance& instance) {}
+
+ static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces) {}
+};
+#endif // DART_PRECOMPILER
+
} // namespace dart
#endif // RUNTIME_VM_PRECOMPILER_H_
« no previous file with comments | « runtime/vm/parser.cc ('k') | runtime/vm/precompiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698