示例#1
0
self& trim()
{
 //annotation
 
 if(is_annotation())
 {
  array<self> content=array_();
  
  //empty
  
  if(content.is_empty())
  {
   clear();
   
   return *this;
  }
  
  //paranoid
 
  check(atom(content.join("")).type()==type());
 
  //update
 
  update(type().me(),content);
  
  return *this;
 }
 
 return *this;
}
示例#2
0
bool should_rename(DexClass *clazz,
    std::vector<std::string>& pre_patterns,
    std::vector<std::string>& post_patterns,
    std::unordered_set<const DexType*>& untouchables,
    bool rename_annotations,
    PassManager& mgr) {
  if (!rename_annotations && is_annotation(clazz)) {
    mgr.incr_metric(METRIC_CANT_RENAME_ANNOTATION, 1);
    return false;
  }
  if (untouchables.count(clazz->get_type())) {
    mgr.incr_metric(METRIC_CANT_RENAME_UNTOUCHABLE, 1);
    return false;
  }
  auto chstring = clazz->get_type()->get_name()->c_str();
  /* We're assuming anonymous classes are safe always safe to rename. */
  auto last_cash = strrchr(chstring, '$');
  if (last_cash != nullptr) {
    auto val = *++last_cash;
    if (val >= '0' && val <= '9') {
      match_inner++;
      return true;
    }
  }
  /* Check for more aggressive, but finer grained filters first */
  for (auto p : pre_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  if (!can_rename(clazz) && !can_delete(clazz)) {
    mgr.incr_metric(METRIC_CANT_RENAME_AND_CANT_DELETE, 1);
    return false;
  }
  /* Check for wider, less precise filters */
  for (auto p : post_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  mgr.incr_metric(METRIC_NOT_WHITELISTED, 1);
  return false;
}
示例#3
0
bool should_rename(DexClass *clazz,
    std::vector<std::string>& pre_patterns,
    std::vector<std::string>& post_patterns,
    std::unordered_set<const DexType*>& untouchables,
    bool rename_annotations) {
  if (!rename_annotations && is_annotation(clazz)) return false;
  if (untouchables.count(clazz->get_type())) return false;
  auto chstring = clazz->get_type()->get_name()->c_str();
  /* We're assuming anonymous classes are safe always safe to rename. */
  auto substr = strrchr(chstring, '$');
  if (substr != nullptr) {
    auto val = *++substr;
    if (val >= '0' && val <= '9') {
      match_inner++;
      return true;
    }
  }
  /* Check for more aggressive, but finer grained filters first */
  for (auto p : pre_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  if (!can_rename(clazz) && !can_delete(clazz)) {
    return false;
  }
  /* Check for wider, less precise filters */
  for (auto p : post_patterns) {
    auto substr = strstr(chstring, p.c_str());
    if (substr != nullptr) {
      if (p.length() > 1) {
        match_long++;
      } else {
        match_short++;
      }
      return true;
    }
  }
  return false;
}
示例#4
0
文件: explicit.cpp 项目: avigad/lean
bool is_as_atomic(expr const & e) { return is_annotation(e, *g_as_atomic_name); }
示例#5
0
文件: explicit.cpp 项目: avigad/lean
bool is_as_is(expr const & e) { return is_annotation(e, *g_as_is_name); }
示例#6
0
文件: explicit.cpp 项目: avigad/lean
bool is_partial_explicit(expr const & e) { return is_annotation(e, *g_partial_explicit_name); }
示例#7
0
bool is_consume_args(expr const & e) { return is_annotation(e, *g_consume_args_name); }
示例#8
0
void RemoveBuildersPass::run_pass(DexStoresVector& stores,
                                  ConfigFiles&,
                                  PassManager& mgr) {
  if (mgr.no_proguard_rules()) {
    TRACE(BUILDERS,
          1,
          "RemoveBuildersPass did not run because no Proguard configuration "
          "was provided.");
    return;
  }

  // Initialize couters.
  b_counter = {0, 0, 0, 0};

  auto obj_type = get_object_type();
  auto scope = build_class_scope(stores);
  for (DexClass* cls : scope) {
    if (is_annotation(cls) || is_interface(cls) ||
        cls->get_super_class() != obj_type) {
      continue;
    }

    if (has_builder_name(cls->get_type())) {
      m_builders.emplace(cls->get_type());
    }
  }

  std::unordered_set<DexType*> escaped_builders;
  walk::methods(scope, [&](DexMethod* m) {
    auto builders = created_builders(m);
    for (DexType* builder : builders) {
      if (escapes_stack(builder, m)) {
        TRACE(BUILDERS,
              3,
              "%s escapes in %s\n",
              SHOW(builder),
              m->get_deobfuscated_name().c_str());
        escaped_builders.emplace(builder);
      }
    }
  });

  std::unordered_set<DexType*> stack_only_builders;
  for (DexType* builder : m_builders) {
    if (escaped_builders.find(builder) == escaped_builders.end()) {
      stack_only_builders.emplace(builder);
    }
  }

  std::unordered_set<DexType*> builders_and_supers;
  for (DexType* builder : stack_only_builders) {
    DexType* cls = builder;
    while (cls != nullptr && cls != obj_type) {
      builders_and_supers.emplace(cls);
      cls = type_class(cls)->get_super_class();
    }
  }

  std::unordered_set<DexType*> this_escapes;
  for (DexType* cls_ty : builders_and_supers) {
    DexClass* cls = type_class(cls_ty);
    if (cls->is_external() ||
        this_arg_escapes(cls, m_enable_buildee_constr_change)) {
      this_escapes.emplace(cls_ty);
    }
  }

  // set of builders that neither escape the stack nor pass their 'this' arg
  // to another function
  std::unordered_set<DexType*> no_escapes;
  for (DexType* builder : stack_only_builders) {
    DexType* cls = builder;
    bool hierarchy_has_escape = false;
    while (cls != nullptr) {
      if (this_escapes.find(cls) != this_escapes.end()) {
        hierarchy_has_escape = true;
        break;
      }
      cls = type_class(cls)->get_super_class();
    }
    if (!hierarchy_has_escape) {
      no_escapes.emplace(builder);
    }
  }

  size_t dmethod_count = 0;
  size_t vmethod_count = 0;
  size_t build_count = 0;
  for (DexType* builder : no_escapes) {
    auto cls = type_class(builder);
    auto buildee = get_buildee(builder);
    dmethod_count += cls->get_dmethods().size();
    vmethod_count += cls->get_vmethods().size();
    for (DexMethod* m : cls->get_vmethods()) {
      if (m->get_proto()->get_rtype() == buildee) {
        build_count++;
      }
    }
  }

  std::unordered_set<DexClass*> trivial_builders =
      get_trivial_builders(m_builders, no_escapes);

  std::unordered_set<DexClass*> kept_builders =
      get_builders_with_subclasses(scope);

  PassConfig pc(mgr.get_config());
  BuilderTransform b_transform(pc, scope, stores, false);

  // Inline non init methods.
  std::unordered_set<DexClass*> removed_builders;
  walk::methods(scope, [&](DexMethod* method) {
    auto builders = created_builders(method);

    for (DexType* builder : builders) {
      if (method->get_class() == builder) {
        continue;
      }

      DexClass* builder_cls = type_class(builder);

      // Filter out builders that we cannot remove.
      if (kept_builders.find(builder_cls) != kept_builders.end()) {
        continue;
      }

      // Check it is a trivial one.
      if (trivial_builders.find(builder_cls) != trivial_builders.end()) {

        DexMethod* method_copy = DexMethod::make_method_from(
            method,
            method->get_class(),
            DexString::make_string(method->get_name()->str() +
                                   "$redex_builders"));
        bool was_not_removed =
            !b_transform.inline_methods(
                method, builder, &get_non_init_methods) ||
            !remove_builder_from(method, builder_cls, b_transform);

        if (was_not_removed) {
          kept_builders.emplace(builder_cls);
          method->set_code(method_copy->release_code());
        } else {
          b_counter.methods_cleared++;
          removed_builders.emplace(builder_cls);
        }

        DexMethod::erase_method(method_copy);
      }
    }
  });

  // No need to remove the builders here, since `RemoveUnreachable` will
  // take care of it.
  gather_removal_builder_stats(removed_builders, kept_builders);

  mgr.set_metric("total_builders", m_builders.size());
  mgr.set_metric("stack_only_builders", stack_only_builders.size());
  mgr.set_metric("no_escapes", no_escapes.size());
  mgr.incr_metric(METRIC_CLASSES_REMOVED, b_counter.classes_removed);
  mgr.incr_metric(METRIC_METHODS_REMOVED, b_counter.methods_removed);
  mgr.incr_metric(METRIC_FIELDS_REMOVED, b_counter.fields_removed);
  mgr.incr_metric(METRIC_METHODS_CLEARED, b_counter.methods_cleared);

  TRACE(BUILDERS, 1, "Total builders: %d\n", m_builders.size());
  TRACE(BUILDERS, 1, "Stack-only builders: %d\n", stack_only_builders.size());
  TRACE(BUILDERS,
        1,
        "Stack-only builders that don't let `this` escape: %d\n",
        no_escapes.size());
  TRACE(BUILDERS, 1, "Stats for unescaping builders:\n");
  TRACE(BUILDERS, 1, "\tdmethods: %d\n", dmethod_count);
  TRACE(BUILDERS, 1, "\tvmethods: %d\n", vmethod_count);
  TRACE(BUILDERS, 1, "\tbuild methods: %d\n", build_count);
  TRACE(BUILDERS, 1, "Trivial builders: %d\n", trivial_builders.size());
  TRACE(BUILDERS, 1, "Classes removed: %d\n", b_counter.classes_removed);
  TRACE(BUILDERS, 1, "Methods removed: %d\n", b_counter.methods_removed);
  TRACE(BUILDERS, 1, "Fields removed: %d\n", b_counter.fields_removed);
  TRACE(BUILDERS, 1, "Methods cleared: %d\n", b_counter.methods_cleared);
}
示例#9
0
bool is_by(expr const & e) { return is_annotation(e, *g_by_name); }
示例#10
0
ClassSpecification parse_class_specification(
    std::vector<unique_ptr<Token>>::iterator* it, bool* ok) {
  ClassSpecification class_spec;
  *ok = true;
  class_spec.annotationType = parse_annotation_type(it);
  if (!parse_access_flags(
          it, class_spec.setAccessFlags, class_spec.unsetAccessFlags)) {
    // There was a problem parsing the access flags. Return an empty class spec
    // for now.
    std::cerr << "Problem parsing access flags for class specification.\n";
    *ok = false;
    return class_spec;
  }
  // According to the ProGuard grammer the next token could be a '!' to express
  // a rule that
  // says !class or !interface or !enum. We choose to not implement this
  // feature.
  if ((**it)->type == token::notToken) {
    cerr << "Keep rules that match the negation of class, interface or enum "
            "are not supported.\n";
    *ok = false;
    return class_spec;
  }
  bool match_annotation_class = is_annotation(class_spec.setAccessFlags);
  if (!match_annotation_class) {
    // Make sure the next keyword is interface, class, enum.
    if (!(((**it)->type == token::interface) ||
          ((**it)->type == token::classToken) ||
          ((**it)->type == token::enumToken ||
           ((**it)->type == token::annotation)))) {
      cerr << "Expected interface, class or enum but got " << (**it)->show()
           << " at line number " << (**it)->line << endl;
      *ok = false;
      return class_spec;
    }
    // Restrict matches to interface classes
    if ((**it)->type == token::interface) {
      set_access_flag(class_spec.setAccessFlags, ACC_INTERFACE);
    }
    // Restrict matches to enum classes
    if ((**it)->type == token::enumToken) {
      set_access_flag(class_spec.setAccessFlags, ACC_ENUM);
    }
    ++(*it);
  }
  // Parse the class name.
  if ((**it)->type != token::identifier) {
    cerr << "Expected class name but got " << (**it)->show() << " at line "
         << (**it)->line << endl;
    *ok = false;
    return class_spec;
  }
  class_spec.className = static_cast<Identifier*>((*it)->get())->ident;
  ++(*it);
  // Parse extends/implements if present, treating implements like extends.
  if (((**it)->type == token::extends) || ((**it)->type == token::implements)) {
    ++(*it);
    class_spec.extendsAnnotationType = parse_annotation_type(it);
    if ((**it)->type != token::identifier) {
      cerr << "Expecting a class name after extends/implements but got "
           << (**it)->show() << " at line " << (**it)->line << endl;
      *ok = false;
      class_spec.extendsClassName = "";
    } else {
      class_spec.extendsClassName =
          static_cast<Identifier*>((*it)->get())->ident;
    }
    ++(*it);
  }
  // Parse the member specifications, if there are any
  parse_member_specifications(it, &class_spec, ok);
  std::sort(class_spec.fieldSpecifications.begin(),
            class_spec.fieldSpecifications.end(),
            member_comparison);
  std::sort(class_spec.methodSpecifications.begin(),
            class_spec.methodSpecifications.end(),
            member_comparison);
  return class_spec;
}