Search in sources :

Example 1 with WeaveViolation

use of com.newrelic.weave.violation.WeaveViolation in project newrelic-java-agent by newrelic.

the class PackageValidationResult method processMatches.

/**
 * Process the weave classes and add them to the result map.
 */
private void processMatches(ClassCache classCache, Map<String, ClassNode> classNameToWeaveNode, Map<String, PreparedMatch> results, boolean isBaseMatch, ClassNode errorHandler) throws IOException {
    for (String weaveClassName : classNameToWeaveNode.keySet()) {
        byte[] originalBytes = classCache.getClassResource(weaveClassName);
        if (null == originalBytes) {
            violations.add(new WeaveViolation(WeaveViolationType.MISSING_ORIGINAL_BYTECODE, weaveClassName));
        } else {
            final ClassNode originalClassNode = WeaveUtils.convertToClassNode(originalBytes);
            final ClassNode weaveNode = classNameToWeaveNode.get(weaveClassName);
            final Set<String> requiredClassAnnotations = weavePackage.getRequiredAnnotationClassesForMethodAnnotationWeave(weaveClassName);
            final Set<String> requiredMethodAnnotations = weavePackage.getRequiredAnnotationClassesForMethodAnnotationWeave(weaveClassName);
            buildResults(classCache, originalClassNode, weaveClassName, weaveNode, results, isBaseMatch, requiredClassAnnotations, requiredMethodAnnotations, errorHandler, Collections.<String, byte[]>emptyMap());
        }
    }
}
Also used : SynchronizedClassNode(com.newrelic.weave.utils.SynchronizedClassNode) ClassNode(org.objectweb.asm.tree.ClassNode) WeaveViolation(com.newrelic.weave.violation.WeaveViolation)

Example 2 with WeaveViolation

use of com.newrelic.weave.violation.WeaveViolation in project newrelic-java-agent by newrelic.

the class Reference method validateClassNode.

/**
 * Validate this reference against a class node and return a list of violations indicating what does not match.
 *
 * @param classCache the classloader used to load the original class.
 * @param classNode the original class to match against.
 * @return list of {@link ReferenceViolation}s
 * @throws IOException
 */
List<WeaveViolation> validateClassNode(ClassCache classCache, ClassNode classNode) throws IOException {
    List<WeaveViolation> violations = new ArrayList<>();
    if (!this.className.equals(classNode.name)) {
        violations.add(new ReferenceViolation(WeaveViolationType.INVALID_REFERENCE, referenceOrigin, classNode.name, "class name mismatch"));
    }
    // first check the class accessors
    if (this.requiredAccess.length > 0) {
        int total = 0;
        for (int requiredAcces : requiredAccess) {
            total += requiredAcces;
        }
        if (!WeaveUtils.flagsMatch(total, classNode.access, requiredAccess)) {
            violations.add(new ReferenceViolation(WeaveViolationType.INVALID_REFERENCE, referenceOrigin, classNode.name, "required class access mismatch. weave expects: " + WeaveUtils.humanReadableAccessFlags(total) + " original has: " + WeaveUtils.humanReadableAccessFlags(classNode.access)));
        }
    }
    if (this.illegalAccess.length > 0) {
        if (!WeaveUtils.flagsMatch(0, classNode.access, illegalAccess)) {
            violations.add(new ReferenceViolation(WeaveViolationType.INVALID_REFERENCE, referenceOrigin, classNode.name, "illegal class access mismatch. Original has: " + WeaveUtils.humanReadableAccessFlags(classNode.access)));
        }
    }
    List<MethodNode> originalMethods = new ArrayList<>();
    List<FieldNode> originalFields = new ArrayList<>();
    addMethodsAndFields(classCache, classNode, originalMethods, originalFields);
    // now check the fields and methods
    violations.addAll(validateFieldsAndMethods(classNode.name, originalMethods, originalFields));
    return violations;
}
Also used : ReferenceViolation(com.newrelic.weave.violation.ReferenceViolation) MethodNode(org.objectweb.asm.tree.MethodNode) SynchronizedMethodNode(com.newrelic.weave.utils.SynchronizedMethodNode) SynchronizedFieldNode(com.newrelic.weave.utils.SynchronizedFieldNode) FieldNode(org.objectweb.asm.tree.FieldNode) ArrayList(java.util.ArrayList) WeaveViolation(com.newrelic.weave.violation.WeaveViolation)

Example 3 with WeaveViolation

use of com.newrelic.weave.violation.WeaveViolation in project newrelic-java-agent by newrelic.

the class WeavePackage method processWeaveBytes.

/**
 * Processes all classes in the package.  Part of package initialization.
 * @param weavePackageBytes list of all class bytes in the package
 * @return list of weave violations found during package initialization
 */
protected final List<WeaveViolation> processWeaveBytes(List<byte[]> weavePackageBytes) {
    List<WeaveViolation> violations = new ArrayList<>();
    for (LanguageAdapter adapter : RegisteredLanguageAdapters.getLanguageAdapters()) {
        try {
            LanguageAdapterResult result = adapter.adapt(weavePackageBytes);
            weavePackageBytes = result.getAdaptedBytes();
            violations.addAll(result.getViolations());
        } catch (Throwable ignored) {
        }
    }
    // read weave annotations on each class bytes and put in appropriate map
    for (byte[] weaveClassBytes : weavePackageBytes) {
        ClassNode weaveNode = WeaveUtils.convertToClassNode(weaveClassBytes);
        WeaveClassInfo weave = new WeaveClassInfo(weaveNode);
        violations.addAll(weave.getViolations());
        final boolean isClassAnnotationMatch = !weave.getRequiredClassAnnotations().isEmpty();
        final boolean isMethodAnnotationMatch = !weave.getRequiredMethodAnnotations().isEmpty();
        if (isClassAnnotationMatch || isMethodAnnotationMatch) {
            if (isClassAnnotationMatch) {
                for (String requiredAnnotation : weave.getRequiredClassAnnotations()) {
                    if (weave.getMatchType().equals(Interface)) {
                        baseAnnotationWeaves.put(requiredAnnotation, weaveNode);
                    }
                    allClassAnnotationWeaves.put(requiredAnnotation, weaveNode);
                }
                requiredClassAnnotationsLookup.put(weaveNode.name, weave.getRequiredClassAnnotations());
            }
            if (isMethodAnnotationMatch) {
                for (String requiredAnnotation : weave.getRequiredMethodAnnotations()) {
                    if (!isClassAnnotationMatch) {
                        allMethodAnnotationWeaves.put(requiredAnnotation, weaveNode);
                    } else if (!allMethodAnnotationWeaves.containsKey(requiredAnnotation)) {
                        allMethodAnnotationWeaves.put(requiredAnnotation, weaveNode);
                    }
                }
                requiredMethodAnnotationsLookup.put(weaveNode.name, weave.getRequiredMethodAnnotations());
            }
        } else if (null == weave.getMatchType()) {
            if (weave.isSkipIfPresent()) {
                skipIfPresentClasses.add(weave.getOriginalName());
            } else {
                utilClasses.put(weaveNode.name, weaveNode);
            }
        } else {
            if (!weaveNode.name.equals(weave.getOriginalName())) {
                renames.put(weaveNode.name, weave.getOriginalName());
            }
            // check if added and merge
            weaveMatches.put(weave.getOriginalName(), weave.getMatchType());
            switch(weave.getMatchType()) {
                case BaseClass:
                case Interface:
                    baseWeaves.put(weave.getOriginalName(), weaveNode);
                    break;
                case ExactClass:
                default:
                    exactWeaves.put(weave.getOriginalName(), weaveNode);
                    break;
            }
        }
    }
    // preprocess
    this.preprocessAllWeaveCode();
    this.packageViolations.addAll(violations);
    if (isBootstrapClassName(this.exactWeaves.keySet()) || isBootstrapClassName(this.baseWeaves.keySet())) {
        this.weavesBootstrap = true;
    }
    return violations;
}
Also used : SynchronizedClassNode(com.newrelic.weave.utils.SynchronizedClassNode) ClassNode(org.objectweb.asm.tree.ClassNode) LanguageAdapterResult(com.newrelic.weave.weavepackage.language.LanguageAdapterResult) LanguageAdapter(com.newrelic.weave.weavepackage.language.LanguageAdapter) ArrayList(java.util.ArrayList) WeaveClassInfo(com.newrelic.weave.utils.WeaveClassInfo) WeaveViolation(com.newrelic.weave.violation.WeaveViolation)

Example 4 with WeaveViolation

use of com.newrelic.weave.violation.WeaveViolation in project newrelic-java-agent by newrelic.

the class WeaveTestUtils method weave.

public static ClassWeave weave(ClassNode originalClass, ClassNode weaveClass, ClassNode target, boolean isBaseMatch, Set<String> requiredClassAnnotations, Set<String> requiredMethodAnnotations, ClassNode errorHandlerClassNode, ClassNode extensionTemplate, ClassCache contextCache) throws IOException {
    // match original and weave only if we haven't already done so
    PreparedMatch preparedMatch = MATCHES_ADDED_TO_CLASSLOADER.get(originalClass.name, weaveClass.name);
    if (preparedMatch == null) {
        WeaveClassInfo weaveClassInfo = new WeaveClassInfo(weaveClass);
        // preprocess weave class if original is an interface
        if ((originalClass.access & Opcodes.ACC_INTERFACE) != 0) {
            ClassNode preprocessed = new ClassNode(WeaveUtils.ASM_API_LEVEL);
            Map<String, MatchType> weaveMatches = new HashMap<>();
            weaveMatches.put(weaveClassInfo.getOriginalName(), MatchType.Interface);
            weaveMatches.put(weaveClass.name, MatchType.Interface);
            ClassVisitor preprocessor = MethodProcessors.fixInvocationInstructions(preprocessed, weaveMatches);
            weaveClass.accept(preprocessor);
            weaveClass = preprocessed;
        }
        ClassMatch match = ClassMatch.match(originalClass, weaveClass, isBaseMatch, requiredClassAnnotations, requiredMethodAnnotations, contextCache);
        // weave should not proceed in case of match errors
        for (String newInnerClassName : match.getNewInnerClasses()) {
            match.validateNewInnerClass(readClass(newInnerClassName));
        }
        Collection<WeaveViolation> violations = match.getViolations();
        String assertMsg = String.format("Encountered %d match violations: %s", violations.size(), Iterables.toString(violations));
        assertTrue(assertMsg, violations.isEmpty());
        preparedMatch = PreparedMatch.prepare(match, errorHandlerClassNode, extensionTemplate, true);
        MATCHES_ADDED_TO_CLASSLOADER.put(originalClass.name, weaveClass.name, preparedMatch);
    }
    // weave target using the specified match and add composite class to classloader
    return ClassWeave.weave(preparedMatch, target, null, Collections.emptyMap());
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) MatchType(com.newrelic.api.agent.weaver.MatchType) HashMap(java.util.HashMap) WeaveClassInfo(com.newrelic.weave.utils.WeaveClassInfo) WeaveViolation(com.newrelic.weave.violation.WeaveViolation) ClassVisitor(org.objectweb.asm.ClassVisitor) TraceClassVisitor(org.objectweb.asm.util.TraceClassVisitor)

Example 5 with WeaveViolation

use of com.newrelic.weave.violation.WeaveViolation in project newrelic-java-agent by newrelic.

the class WeaveTestUtils method expectViolations.

/**
 * Validate the WeavePackage against a ClassLoader and assert that exactly the expected violations occur.
 *
 * @param weavePackage package to validate
 * @param classloader classloader to validate against
 * @param expected exepcted violations
 * @throws IOException
 */
public static void expectViolations(WeavePackage weavePackage, ClassLoader classloader, WeaveViolation... expected) throws IOException {
    List<WeaveViolation> actual = weavePackage.validate(new ClassCache(new ClassLoaderFinder(classloader))).getViolations();
    expectViolations(actual, expected);
}
Also used : ClassLoaderFinder(com.newrelic.weave.utils.ClassLoaderFinder) WeaveViolation(com.newrelic.weave.violation.WeaveViolation) ClassCache(com.newrelic.weave.utils.ClassCache)

Aggregations

WeaveViolation (com.newrelic.weave.violation.WeaveViolation)35 Test (org.junit.Test)20 Method (org.objectweb.asm.commons.Method)15 ArrayList (java.util.ArrayList)6 ClassNode (org.objectweb.asm.tree.ClassNode)5 ClassCache (com.newrelic.weave.utils.ClassCache)4 WeavePackage (com.newrelic.weave.weavepackage.WeavePackage)4 ClassLoaderFinder (com.newrelic.weave.utils.ClassLoaderFinder)3 CachedWeavePackage (com.newrelic.weave.weavepackage.CachedWeavePackage)3 ClassMatchVisitorFactory (com.newrelic.agent.instrumentation.context.ClassMatchVisitorFactory)2 SynchronizedClassNode (com.newrelic.weave.utils.SynchronizedClassNode)2 WeaveClassInfo (com.newrelic.weave.utils.WeaveClassInfo)2 PackageValidationResult (com.newrelic.weave.weavepackage.PackageValidationResult)2 WeavePackageConfig (com.newrelic.weave.weavepackage.WeavePackageConfig)2 FileInputStream (java.io.FileInputStream)2 IOException (java.io.IOException)2 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 JarInputStream (java.util.jar.JarInputStream)2