diff --git a/.classpath b/.classpath deleted file mode 100644 index 40e74506e..000000000 --- a/.classpath +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/.fbprefs b/.fbprefs deleted file mode 100644 index ddb0e061e..000000000 --- a/.fbprefs +++ /dev/null @@ -1,160 +0,0 @@ -#FindBugs User Preferences -#Mon Aug 01 18:36:02 CEST 2011 -detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true -detectorBCPMethodReturnCheck=BCPMethodReturnCheck|false -detectorBadAppletConstructor=BadAppletConstructor|false -detectorBadResultSetAccess=BadResultSetAccess|false -detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true -detectorBadUseOfReturnValue=BadUseOfReturnValue|true -detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true -detectorBooleanReturnNull=BooleanReturnNull|true -detectorBuildInterproceduralCallGraph=BuildInterproceduralCallGraph|false -detectorBuildObligationPolicyDatabase=BuildObligationPolicyDatabase|true -detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true -detectorCalledMethods=CalledMethods|true -detectorCheckCalls=CheckCalls|false -detectorCheckExpectedWarnings=CheckExpectedWarnings|false -detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true -detectorCheckTypeQualifiers=CheckTypeQualifiers|true -detectorCloneIdiom=CloneIdiom|true -detectorComparatorIdiom=ComparatorIdiom|false -detectorConfusedInheritance=ConfusedInheritance|true -detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true -detectorCrossSiteScripting=CrossSiteScripting|true -detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true -detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true -detectorDontIgnoreResultOfPutIfAbsent=DontIgnoreResultOfPutIfAbsent|true -detectorDontUseEnum=DontUseEnum|true -detectorDroppedException=DroppedException|true -detectorDumbMethodInvocations=DumbMethodInvocations|true -detectorDumbMethods=DumbMethods|true -detectorDuplicateBranches=DuplicateBranches|true -detectorEmptyZipFileEntry=EmptyZipFileEntry|true -detectorEqStringTest=EqStringTest|false -detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true -detectorFieldItemSummary=FieldItemSummary|true -detectorFinalizerNullsFields=FinalizerNullsFields|true -detectorFindBadCast=FindBadCast|false -detectorFindBadCast2=FindBadCast2|true -detectorFindBadEqualsImplementation=FindBadEqualsImplementation|false -detectorFindBadForLoop=FindBadForLoop|true -detectorFindBugsSummaryStats=FindBugsSummaryStats|true -detectorFindCircularDependencies=FindCircularDependencies|false -detectorFindDeadLocalStores=FindDeadLocalStores|true -detectorFindDoubleCheck=FindDoubleCheck|true -detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true -detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true -detectorFindFinalizeInvocations=FindFinalizeInvocations|true -detectorFindFloatEquality=FindFloatEquality|true -detectorFindFloatMath=FindFloatMath|false -detectorFindHEmismatch=FindHEmismatch|true -detectorFindInconsistentSync2=FindInconsistentSync2|true -detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true -detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true -detectorFindMaskedFields=FindMaskedFields|true -detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true -detectorFindNakedNotify=FindNakedNotify|true -detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|false -detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true -detectorFindNonShortCircuit=FindNonShortCircuit|true -detectorFindNullDeref=FindNullDeref|true -detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true -detectorFindOpenStream=FindOpenStream|true -detectorFindPuzzlers=FindPuzzlers|true -detectorFindRefComparison=FindRefComparison|true -detectorFindReturnRef=FindReturnRef|false -detectorFindRunInvocations=FindRunInvocations|true -detectorFindSelfComparison=FindSelfComparison|true -detectorFindSelfComparison2=FindSelfComparison2|true -detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true -detectorFindSpinLoop=FindSpinLoop|true -detectorFindSqlInjection=FindSqlInjection|false -detectorFindTwoLockWait=FindTwoLockWait|true -detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true -detectorFindUnconditionalWait=FindUnconditionalWait|true -detectorFindUninitializedGet=FindUninitializedGet|true -detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true -detectorFindUnreleasedLock=FindUnreleasedLock|true -detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true -detectorFindUnsyncGet=FindUnsyncGet|true -detectorFindUselessControlFlow=FindUselessControlFlow|true -detectorFormatStringChecker=FormatStringChecker|true -detectorHugeSharedStringConstants=HugeSharedStringConstants|true -detectorIDivResultCastToDouble=IDivResultCastToDouble|true -detectorIncompatMask=IncompatMask|true -detectorInconsistentAnnotations=InconsistentAnnotations|true -detectorInefficientMemberAccess=InefficientMemberAccess|false -detectorInefficientToArray=InefficientToArray|true -detectorInfiniteLoop=InfiniteLoop|true -detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true -detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false -detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true -detectorInitializationChain=InitializationChain|true -detectorInstantiateStaticClass=InstantiateStaticClass|true -detectorInvalidJUnitTest=InvalidJUnitTest|true -detectorIteratorIdioms=IteratorIdioms|true -detectorLazyInit=LazyInit|true -detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true -detectorLockedFields=LockedFields|false -detectorLostLoggerDueToWeakReference=LostLoggerDueToWeakReference|true -detectorMethodReturnCheck=MethodReturnCheck|true -detectorMethods=Methods|true -detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true -detectorMutableLock=MutableLock|true -detectorMutableStaticFields=MutableStaticFields|false -detectorNaming=Naming|true -detectorNoteAnnotationRetention=NoteAnnotationRetention|true -detectorNoteCheckReturnValue=NoteCheckReturnValue|true -detectorNoteCheckReturnValueAnnotations=NoteCheckReturnValueAnnotations|true -detectorNoteDirectlyRelevantTypeQualifiers=NoteDirectlyRelevantTypeQualifiers|true -detectorNoteJCIPAnnotation=NoteJCIPAnnotation|true -detectorNoteNonNullAnnotations=NoteNonNullAnnotations|true -detectorNoteNonnullReturnValues=NoteNonnullReturnValues|true -detectorNoteSuppressedWarnings=NoteSuppressedWarnings|true -detectorNoteUnconditionalParamDerefs=NoteUnconditionalParamDerefs|true -detectorNumberConstructor=NumberConstructor|false -detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true -detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true -detectorPublicSemaphores=PublicSemaphores|true -detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true -detectorReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass=ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass|true -detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true -detectorRedundantInterfaces=RedundantInterfaces|true -detectorReflectiveClasses=ReflectiveClasses|true -detectorRepeatedConditionals=RepeatedConditionals|true -detectorResolveAllReferences=ResolveAllReferences|false -detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true -detectorSerializableIdiom=SerializableIdiom|false -detectorStartInConstructor=StartInConstructor|true -detectorStaticCalendarDetector=StaticCalendarDetector|true -detectorStringConcatenation=StringConcatenation|true -detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true -detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true -detectorSwitchFallthrough=SwitchFallthrough|true -detectorSynchronizationOnSharedBuiltinConstant=SynchronizationOnSharedBuiltinConstant|true -detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true -detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true -detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true -detectorTestASM=TestASM|false -detectorTestDataflowAnalysis=TestDataflowAnalysis|false -detectorTestingGround=TestingGround|false -detectorTrainFieldStoreTypes=TrainFieldStoreTypes|true -detectorTrainNonNullAnnotations=TrainNonNullAnnotations|true -detectorTrainUnconditionalDerefParams=TrainUnconditionalDerefParams|true -detectorURLProblems=URLProblems|true -detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true -detectorUnnecessaryMath=UnnecessaryMath|true -detectorUnreadFields=UnreadFields|true -detectorUseObjectEquals=UseObjectEquals|true -detectorUselessSubclassMethod=UselessSubclassMethod|true -detectorVarArgsProblems=VarArgsProblems|true -detectorVolatileUsage=VolatileUsage|true -detectorWaitInLoop=WaitInLoop|true -detectorWrongMapIterator=WrongMapIterator|true -detectorXMLFactoryBypass=XMLFactoryBypass|true -detector_threshold=2 -effort=max -excludefilter0=findbugsExclude.xml -filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,EXPERIMENTAL,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false -filter_settings_neg=NOISE| -run_at_full_build=false diff --git a/.gitignore b/.gitignore index 6b50e54d9..6caaae3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ -output -plugin.xml -cobertura.ser +# Files generated by Gradle +.gradle/ +build/ + +# Files generated by Eclipse +**/.classpath +**/.gitignore +**/.project +**/.settings/ +**/bin/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..9bb60b118 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,18 @@ +image: gradle:4.6-jdk8-alpine + +variables: + # Set the location of the dependency cache to a local directory, so that it + # can be cached between GitLab Continous Integration Jobs. + GRADLE_USER_HOME: '.gradle' + +cache: + paths: + # Cache the downloaded dependencies and plugins between builds. + - '$GRADLE_USER_HOME' + +build: + script: + - gradle build + - gradle test jacocoTestCoverageVerification + - gradle uploadArchives + - 'gradle sonarqube -Dsonar.host.url=https://sonarqube.ow2.org' diff --git a/.mailmap b/.mailmap new file mode 100644 index 000000000..fcf2beaa6 --- /dev/null +++ b/.mailmap @@ -0,0 +1,8 @@ +# In alphabetical order of family name: +Eric Bruneton +Sebastien Chassande-Barrioz +Remi Forax +Remi Forax +Eugene Kuleshov +Andrei Loskutov + diff --git a/.project b/.project deleted file mode 100644 index 0d7449507..000000000 --- a/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - asm3 - - - - - - org.eclipse.jdt.core.javabuilder - - - - - edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder - - - - - - org.eclipse.jdt.core.javanature - edu.umd.cs.findbugs.plugin.eclipse.findbugsNature - - - - 1436861125301 - - 26 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-.svn - - - - diff --git a/.settings/de.loskutov.anyedit.AnyEditTools.prefs b/.settings/de.loskutov.anyedit.AnyEditTools.prefs deleted file mode 100644 index 98be28bcc..000000000 --- a/.settings/de.loskutov.anyedit.AnyEditTools.prefs +++ /dev/null @@ -1,16 +0,0 @@ -#Mon Sep 12 22:02:30 CEST 2011 -activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF -addNewLine=false -convertActionOnSaave=AnyEdit.CnvrtTabToSpaces -eclipse.preferences.version=1 -inActiveContentFilterList= -javaTabWidthForJava=true -org.eclipse.jdt.ui.editor.tab.width=4 -projectPropsEnabled=true -removeTrailingSpaces=true -replaceAllSpaces=false -replaceAllTabs=false -saveAndAddLine=false -saveAndConvert=false -saveAndTrim=true -useModulo4Tabs=false diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 392fdaefd..000000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,384 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled -org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore -org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull -org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault -org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable -org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.autoboxing=ignore -org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning -org.eclipse.jdt.core.compiler.problem.deadCode=warning -org.eclipse.jdt.core.compiler.problem.deprecation=warning -org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled -org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled -org.eclipse.jdt.core.compiler.problem.discouragedReference=warning -org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning -org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning -org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled -org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore -org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore -org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error -org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning -org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled -org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning -org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore -org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning -org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore -org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning -org.eclipse.jdt.core.compiler.problem.missingDefaultCase=warning -org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore -org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled -org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning -org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled -org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore -org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore -org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning -org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning -org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore -org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning -org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error -org.eclipse.jdt.core.compiler.problem.nullReference=warning -org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error -org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning -org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning -org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore -org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore -org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore -org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning -org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning -org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore -org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning -org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore -org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore -org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled -org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning -org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled -org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled -org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=enabled -org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning -org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning -org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled -org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning -org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning -org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore -org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning -org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore -org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning -org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore -org.eclipse.jdt.core.compiler.problem.unsafeTypeOperation=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled -org.eclipse.jdt.core.compiler.problem.unusedImport=warning -org.eclipse.jdt.core.compiler.problem.unusedLabel=warning -org.eclipse.jdt.core.compiler.problem.unusedLocal=warning -org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore -org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled -org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled -org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning -org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning -org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning -org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=ignore -org.eclipse.jdt.core.compiler.source=1.5 -org.eclipse.jdt.core.formatter.align_type_members_on_columns=false -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_assignment=0 -org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 -org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 -org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 -org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 -org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 -org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 -org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 -org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 -org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 -org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 -org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_after_package=1 -org.eclipse.jdt.core.formatter.blank_lines_before_field=0 -org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 -org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 -org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 -org.eclipse.jdt.core.formatter.blank_lines_before_method=1 -org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 -org.eclipse.jdt.core.formatter.blank_lines_before_package=0 -org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 -org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 -org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line -org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line -org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false -org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false -org.eclipse.jdt.core.formatter.comment.format_block_comments=true -org.eclipse.jdt.core.formatter.comment.format_comments=true -org.eclipse.jdt.core.formatter.comment.format_header=false -org.eclipse.jdt.core.formatter.comment.format_html=true -org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true -org.eclipse.jdt.core.formatter.comment.format_line_comments=true -org.eclipse.jdt.core.formatter.comment.format_source_code=true -org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true -org.eclipse.jdt.core.formatter.comment.indent_root_tags=true -org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert -org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert -org.eclipse.jdt.core.formatter.comment.line_length=80 -org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true -org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true -org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false -org.eclipse.jdt.core.formatter.compact_else_if=true -org.eclipse.jdt.core.formatter.continuation_indentation=2 -org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 -org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off -org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on -org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false -org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true -org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true -org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_empty_lines=false -org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true -org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true -org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false -org.eclipse.jdt.core.formatter.indentation.size=8 -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert -org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert -org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert -org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert -org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert -org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert -org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert -org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert -org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert -org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert -org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert -org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert -org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert -org.eclipse.jdt.core.formatter.join_lines_in_comments=true -org.eclipse.jdt.core.formatter.join_wrapped_lines=true -org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false -org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false -org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false -org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false -org.eclipse.jdt.core.formatter.lineSplit=80 -org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false -org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false -org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 -org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 -org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true -org.eclipse.jdt.core.formatter.tabulation.char=space -org.eclipse.jdt.core.formatter.tabulation.size=4 -org.eclipse.jdt.core.formatter.use_on_off_tags=false -org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false -org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true -org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true -org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs deleted file mode 100644 index 39b2ba165..000000000 --- a/.settings/org.eclipse.jdt.ui.prefs +++ /dev/null @@ -1,15 +0,0 @@ -#Sat Aug 18 17:43:18 CEST 2012 -comment_clear_blank_lines=false -comment_format_comments=true -comment_format_header=false -comment_format_html=false -comment_format_source_code=false -comment_indent_parameter_description=false -comment_indent_root_tags=true -comment_line_length=80 -comment_new_line_for_parameter=false -comment_separate_root_tags=true -eclipse.preferences.version=1 -formatter_profile=_Java conventions without tabs -formatter_settings_version=12 -org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/.settings/org.eclipse.mylar.tasklist.prefs b/.settings/org.eclipse.mylar.tasklist.prefs deleted file mode 100644 index 1c406936b..000000000 --- a/.settings/org.eclipse.mylar.tasklist.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Tue Nov 21 01:22:11 EST 2006 -eclipse.preferences.version=1 -project.repository.kind=web -project.repository.url=http\://forge.objectweb.org/tracker diff --git a/README.txt b/README.txt deleted file mode 100644 index b4c0a05f6..000000000 --- a/README.txt +++ /dev/null @@ -1,48 +0,0 @@ -******************************************************************************* -* ASM: a very small and fast Java bytecode manipulation framework -* Copyright (c) 2000-2011 INRIA, France Telecom -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holders nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -* THE POSSIBILITY OF SUCH DAMAGE. -******************************************************************************* - -This directory is the base directory of the product. -It contains(*) the following items: - -- archive: ant files to build the jar(s) of the product, -- build.properties: properties to configure the build process, -- build.xml: main ant file to build the product, -- config: external libraries required only for building the product, -- doc: documentation of the product, -- etc: scripts to run the product, -- examples: examples of use of the product, -- externals: external libraires required for running the product, -- jdoc: ant files to build the javadoc documentation(s) of the product, -- sr': sources of the product, -- test: tests of the product, -- web: source of the web site of the product. - -(*) some items may not be present, depending on the product. - diff --git a/archive/README.txt b/archive/README.txt deleted file mode 100644 index 35155ac48..000000000 --- a/archive/README.txt +++ /dev/null @@ -1,60 +0,0 @@ -******************************************************************************* -* ASM: a very small and fast Java bytecode manipulation framework -* Copyright (c) 2000-2011 INRIA, France Telecom -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. Neither the name of the copyright holders nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -* THE POSSIBILITY OF SUCH DAMAGE. -******************************************************************************* - -This directory contains ant files to build the jars of the product. -The following rules describe the convention to write such files: - -- An ant file must build only one jar file. - -- The name of the ant file must be the name of the jar it builds: - org-foo-bar.xml must build org-foo-bar.jar. - -- Among the elements which are included into a jar, you must specify - a manifest. It is adviced to store the manifest file in this directory. - The manifest file can be shared by several jars. The name of the manifest - file must be similar to the name of the jar file. - -- Only the default task is called on each ant file. - -- The jar file must be produced into the ${dist.lib} directory. - -Sample ant file: - - - - - - ... - - - - diff --git a/archive/asm-analysis.bnd b/archive/asm-analysis.bnd deleted file mode 100644 index 81cb828a0..000000000 --- a/archive/asm-analysis.bnd +++ /dev/null @@ -1,64 +0,0 @@ -############################################################################### -#ASM: a very small and fast Java bytecode manipulation framework -#Copyright (c) 2000-2011 INRIA, France Telecom -#All rights reserved. -# -#Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions -#are met: -#1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -#2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -#3. Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -#THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### - - -Implementation-Title: ASM static code analysis framework -Implementation-Version: ${product.artifact} -Implementation-Vendor: France Telecom R&D - -Bundle-Name: ASM static code analysis framework -Bundle-Vendor: France Telecom R&D -Bundle-Version: ${product.artifact} -Bundle-DocURL: http://asm.objectweb.org -Bundle-SymbolicName: org.objectweb.asm.analysis - -Export-Package: \ - org.objectweb.asm.tree.analysis;version=${product.artifact} - -Import-Package: \ - org.objectweb.asm.*;version="[${product.artifact},${product.artifact}]" - -Module-Requires: \ - org.objectweb.asm;transitive=true, \ - org.objectweb.asm.tree;transitive=true - --pluginpath: \ - ${out.build}/bnd-module-plugin.jar - --plugin.asm: \ - org.objectweb.asm.tools.ModuleInfoBndPlugin; - - -Bundle-RequiredExecutionEnvironment: J2SE-1.3 - --removeheaders:\ - DSTAMP,\ - TODAY,\ - TSTAMP diff --git a/archive/asm-analysis.pom b/archive/asm-analysis.pom deleted file mode 100644 index 47273a1b9..000000000 --- a/archive/asm-analysis.pom +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - - asm-parent - org.ow2.asm - @product.artifact@ - - - ASM Analysis - asm-analysis - jar - - - - asm-tree - org.ow2.asm - - - - diff --git a/archive/asm-analysis.xml b/archive/asm-analysis.xml deleted file mode 100644 index a660a0dc4..000000000 --- a/archive/asm-analysis.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/asm-commons.bnd b/archive/asm-commons.bnd deleted file mode 100644 index 4329b5b42..000000000 --- a/archive/asm-commons.bnd +++ /dev/null @@ -1,63 +0,0 @@ -############################################################################### -#ASM: a very small and fast Java bytecode manipulation framework -#Copyright (c) 2000-2011 INRIA, France Telecom -#All rights reserved. -# -#Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions -#are met: -#1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -#2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -#3. Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -#THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### - - -Implementation-Title: ASM commons classes -Implementation-Version: ${product.artifact} -Implementation-Vendor: France Telecom R&D - -Bundle-Name: ASM commons classes -Bundle-Vendor: France Telecom R&D -Bundle-Version: ${product.artifact} -Bundle-DocURL: http://asm.objectweb.org -Bundle-SymbolicName: org.objectweb.asm.commons - -Export-Package: \ - org.objectweb.asm.commons;version=${product.artifact} - -Import-Package: \ - org.objectweb.asm.*;version="[${product.artifact},${product.artifact}]" - -Module-Requires: \ - org.objectweb.asm;transitive=true, \ - org.objectweb.asm.tree;transitive=true - -Bundle-RequiredExecutionEnvironment: J2SE-1.4 - --pluginpath: \ - ${out.build}/bnd-module-plugin.jar - --plugin.asm: \ - org.objectweb.asm.tools.ModuleInfoBndPlugin; - --removeheaders:\ - DSTAMP,\ - TODAY,\ - TSTAMP diff --git a/archive/asm-commons.pom b/archive/asm-commons.pom deleted file mode 100644 index eaccb73a3..000000000 --- a/archive/asm-commons.pom +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - - asm-parent - org.ow2.asm - @product.artifact@ - - - ASM Commons - asm-commons - jar - - - - asm-tree - org.ow2.asm - - - - diff --git a/archive/asm-commons.xml b/archive/asm-commons.xml deleted file mode 100644 index f7a6258d1..000000000 --- a/archive/asm-commons.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/asm-parent.pom b/archive/asm-parent.pom deleted file mode 100644 index 0f30c8e49..000000000 --- a/archive/asm-parent.pom +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - ow2 - org.ow2 - 1.3 - - - 4.0.0 - - asm-parent - org.ow2.asm - @product.artifact@ - pom - - ASM - A very small and fast Java bytecode manipulation framework - http://asm.objectweb.org/ - - - ObjectWeb - http://www.objectweb.org/ - - 2000 - - - - BSD - http://asm.objectweb.org/license.html - - - - - - Eric Bruneton - ebruneton - ebruneton@free.fr - - Creator - Java Developer - - - - Eugene Kuleshov - eu - eu@javatx.org - - Java Developer - - - - Remi Forax - forax - forax@univ-mlv.fr - - Java Developer - - - - - - scm:svn:svn://svn.forge.objectweb.org/svnroot/asm/trunk - scm:svn:svn+ssh://${maven.username}@svn.forge.objectweb.org/svnroot/asm/trunk - http://svn.forge.objectweb.org/cgi-bin/viewcvs.cgi/asm/trunk/ - - - - http://forge.objectweb.org/tracker/?group_id=23 - - - - - - - asm - ${project.groupId} - ${project.version} - - - - asm-tree - ${project.groupId} - ${project.version} - - - - asm-analysis - ${project.groupId} - ${project.version} - - - - asm-commons - ${project.groupId} - ${project.version} - - - - asm-util - ${project.groupId} - ${project.version} - - - - asm-xml - ${project.groupId} - ${project.version} - - - - - - - - ASM Users List - sympa@objectweb.org?subject=subscribe%20asm - sympa@objectweb.org?subject=unsubscribe%20asm - asm@objectweb.org - http://www.objectweb.org/wws/arc/asm - - - ASM Team List - sympa@objectweb.org?subject=subscribe%20asm-team - sympa@objectweb.org?subject=unsubscribe%20asm-team - asm-team@objectweb.org - http://www.objectweb.org/wws/arc/asm-team - - - - diff --git a/archive/asm-parent.xml b/archive/asm-parent.xml deleted file mode 100644 index 11381f79c..000000000 --- a/archive/asm-parent.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/archive/asm-tree.bnd b/archive/asm-tree.bnd deleted file mode 100644 index 6ec43d50a..000000000 --- a/archive/asm-tree.bnd +++ /dev/null @@ -1,62 +0,0 @@ -############################################################################### -#ASM: a very small and fast Java bytecode manipulation framework -#Copyright (c) 2000-2011 INRIA, France Telecom -#All rights reserved. -# -#Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions -#are met: -#1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -#2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -#3. Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -#THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### - - -Implementation-Title: ASM Tree class visitor -Implementation-Version: ${product.artifact} -Implementation-Vendor: France Telecom R&D - -Bundle-Name: ASM Tree class visitor -Bundle-Vendor: France Telecom R&D -Bundle-Version: ${product.artifact} -Bundle-DocURL: http://asm.objectweb.org -Bundle-SymbolicName: org.objectweb.asm.tree - -Export-Package: \ - org.objectweb.asm.tree;version=${product.artifact} - -Import-Package: \ - org.objectweb.asm.*;version="[${product.artifact},${product.artifact}]" - -Module-Requires: \ - org.objectweb.asm;transitive=true - -Bundle-RequiredExecutionEnvironment: J2SE-1.3 - --pluginpath: \ - ${out.build}/bnd-module-plugin.jar - --plugin.asm: \ - org.objectweb.asm.tools.ModuleInfoBndPlugin; - --removeheaders:\ - DSTAMP,\ - TODAY,\ - TSTAMP diff --git a/archive/asm-tree.pom b/archive/asm-tree.pom deleted file mode 100644 index 624120bb4..000000000 --- a/archive/asm-tree.pom +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - - asm-parent - org.ow2.asm - @product.artifact@ - - - ASM Tree - asm-tree - jar - - - - asm - org.ow2.asm - - - - diff --git a/archive/asm-tree.xml b/archive/asm-tree.xml deleted file mode 100644 index eaff0a305..000000000 --- a/archive/asm-tree.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/asm-util.bnd b/archive/asm-util.bnd deleted file mode 100644 index 0a5abd15a..000000000 --- a/archive/asm-util.bnd +++ /dev/null @@ -1,62 +0,0 @@ -############################################################################### -#ASM: a very small and fast Java bytecode manipulation framework -#Copyright (c) 2000-2011 INRIA, France Telecom -#All rights reserved. -# -#Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions -#are met: -#1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -#2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -#3. Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -#THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### - - -Implementation-Title: ASM Utilities -Implementation-Version: ${product.artifact} -Implementation-Vendor: France Telecom R&D - -Bundle-Name: ASM Utilities -Bundle-Vendor: France Telecom R&D -Bundle-Version: ${product.artifact} -Bundle-DocURL: http://asm.objectweb.org -Bundle-SymbolicName: org.objectweb.asm.util - -Export-Package: \ - org.objectweb.asm.util;version=${product.artifact} - -Import-Package: \ - org.objectweb.asm.*;version="[${product.artifact},${product.artifact}]" - -Module-Requires: \ - org.objectweb.asm;transitive=true - -Bundle-RequiredExecutionEnvironment: J2SE-1.3 - --pluginpath: \ - ${out.build}/bnd-module-plugin.jar - --plugin.asm: \ - org.objectweb.asm.tools.ModuleInfoBndPlugin; - --removeheaders:\ - DSTAMP,\ - TODAY,\ - TSTAMP diff --git a/archive/asm-util.pom b/archive/asm-util.pom deleted file mode 100644 index 065ddd834..000000000 --- a/archive/asm-util.pom +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - - asm-parent - org.ow2.asm - @product.artifact@ - - - ASM Util - asm-util - jar - - - - asm-tree - org.ow2.asm - - - - diff --git a/archive/asm-util.xml b/archive/asm-util.xml deleted file mode 100644 index d467c5aac..000000000 --- a/archive/asm-util.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/asm-xml.bnd b/archive/asm-xml.bnd deleted file mode 100644 index fd35eca13..000000000 --- a/archive/asm-xml.bnd +++ /dev/null @@ -1,66 +0,0 @@ -############################################################################### -#ASM: a very small and fast Java bytecode manipulation framework -#Copyright (c) 2000-2011 INRIA, France Telecom -#All rights reserved. -# -#Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions -#are met: -#1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -#2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -#3. Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -#THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### - - -Implementation-Title: ASM XML classes -Implementation-Version: ${product.artifact} -Implementation-Vendor: Eugene Kuleshov -Class-Path: asm-${product.artifact}.jar asm-util-${product.artifact}.jar -Main-Class: org.objectweb.asm.xml.Processor - -Bundle-Name: ASM xml classes -Bundle-Vendor: France Telecom R&D -Bundle-Version: ${product.artifact} -Bundle-DocURL: http://asm.objectweb.org -Bundle-SymbolicName: org.objectweb.asm.xml - -Export-Package: \ - org.objectweb.asm.xml;version=${product.artifact} - -Import-Package: \ - javax.xml.transform.*;resolution:="optional",\ - org.xml.sax.*;resolution:="optional" - -Module-Requires: \ - java.xml;transitive=true,\ - org.objectweb.asm;transitive=true - -Bundle-RequiredExecutionEnvironment: J2SE-1.5 - --pluginpath: \ - ${out.build}/bnd-module-plugin.jar - --plugin.asm: \ - org.objectweb.asm.tools.ModuleInfoBndPlugin; - --removeheaders:\ - DSTAMP,\ - TODAY,\ - TSTAMP diff --git a/archive/asm-xml.pom b/archive/asm-xml.pom deleted file mode 100644 index a95e658ec..000000000 --- a/archive/asm-xml.pom +++ /dev/null @@ -1,51 +0,0 @@ - - - - 4.0.0 - - - asm-parent - org.ow2.asm - @product.artifact@ - - - ASM XML - asm-xml - jar - - - - asm-util - org.ow2.asm - - - - diff --git a/archive/asm-xml.xml b/archive/asm-xml.xml deleted file mode 100644 index 570eebc04..000000000 --- a/archive/asm-xml.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/archive/asm.bnd b/archive/asm.bnd deleted file mode 100644 index fbf5272f4..000000000 --- a/archive/asm.bnd +++ /dev/null @@ -1,57 +0,0 @@ -############################################################################### -#ASM: a very small and fast Java bytecode manipulation framework -#Copyright (c) 2000-2011 INRIA, France Telecom -#All rights reserved. -# -#Redistribution and use in source and binary forms, with or without -#modification, are permitted provided that the following conditions -#are met: -#1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -#2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -#3. Neither the name of the copyright holders nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -#ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -#LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -#SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -#INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -#CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -#ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -#THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### - - -Implementation-Title: ASM -Implementation-Version: ${product.artifact} -Implementation-Vendor: France Telecom R&D - -Bundle-Name: ASM -Bundle-Vendor: France Telecom R&D -Bundle-Version: ${product.artifact} -Bundle-DocURL: http://asm.objectweb.org -Bundle-SymbolicName: org.objectweb.asm - -Export-Package: \ - org.objectweb.asm;version=${product.artifact}, \ - org.objectweb.asm.signature;version=${product.artifact} - -Bundle-RequiredExecutionEnvironment: J2SE-1.3 - --pluginpath: \ - ${out.build}/bnd-module-plugin.jar - --plugin.asm: \ - org.objectweb.asm.tools.ModuleInfoBndPlugin; - --removeheaders:\ - DSTAMP,\ - TODAY,\ - TSTAMP diff --git a/archive/asm.pom b/archive/asm.pom deleted file mode 100644 index 2f5735389..000000000 --- a/archive/asm.pom +++ /dev/null @@ -1,44 +0,0 @@ - - - - 4.0.0 - - - asm-parent - org.ow2.asm - @product.artifact@ - - - ASM Core - asm - jar - - diff --git a/archive/asm.xml b/archive/asm.xml deleted file mode 100644 index 23bd1714c..000000000 --- a/archive/asm.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Analyzer.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Analyzer.java new file mode 100644 index 000000000..73113e9cc --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Analyzer.java @@ -0,0 +1,586 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LookupSwitchInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.TableSwitchInsnNode; +import org.objectweb.asm.tree.TryCatchBlockNode; +import org.objectweb.asm.tree.VarInsnNode; + +/** + * A semantic bytecode analyzer. This class does not fully check that JSR and RET instructions + * are valid. + * + * @param type of the Value used for the analysis. + * @author Eric Bruneton + */ +public class Analyzer implements Opcodes { + + /** The interpreter to use to symbolically interpret the bytecode instructions. */ + private final Interpreter interpreter; + + /** The instructions of the currently analyzed method. */ + private InsnList insnList; + + /** The size of {@link #insnList}. */ + private int insnListSize; + + /** The exception handlers of the currently analyzed method (one list per instruction index). */ + private List[] handlers; + + /** The execution stack frames of the currently analyzed method (one per instruction index). */ + private Frame[] frames; + + /** The subroutines of the currently analyzed method (one per instruction index). */ + private Subroutine[] subroutines; + + /** The instructions that remain to process (one boolean per instruction index). */ + private boolean[] inInstructionsToProcess; + + /** The indices of the instructions that remain to process in the currently analyzed method. */ + private int[] instructionsToProcess; + + /** The number of instructions that remain to process in the currently analyzed method. */ + private int numInstructionsToProcess; + + /** + * Constructs a new {@link Analyzer}. + * + * @param interpreter the interpreter to use to symbolically interpret the bytecode instructions. + */ + public Analyzer(final Interpreter interpreter) { + this.interpreter = interpreter; + } + + /** + * Analyzes the given method. + * + * @param owner the internal name of the class to which 'method' belongs. + * @param method the method to be analyzed. + * @return the symbolic state of the execution stack frame at each bytecode instruction of the + * method. The size of the returned array is equal to the number of instructions (and labels) + * of the method. A given frame is null if and only if the corresponding instruction + * cannot be reached (dead code). + * @throws AnalyzerException if a problem occurs during the analysis. + */ + @SuppressWarnings("unchecked") + public Frame[] analyze(final String owner, final MethodNode method) throws AnalyzerException { + if ((method.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) { + frames = (Frame[]) new Frame[0]; + return frames; + } + insnList = method.instructions; + insnListSize = insnList.size(); + handlers = (List[]) new List[insnListSize]; + frames = (Frame[]) new Frame[insnListSize]; + subroutines = new Subroutine[insnListSize]; + inInstructionsToProcess = new boolean[insnListSize]; + instructionsToProcess = new int[insnListSize]; + numInstructionsToProcess = 0; + + // For each exception handler, and each instruction within its range, record in 'handlers' the + // fact that execution can flow from this instruction to the exception handler. + for (int i = 0; i < method.tryCatchBlocks.size(); ++i) { + TryCatchBlockNode tryCatchBlock = method.tryCatchBlocks.get(i); + int startIndex = insnList.indexOf(tryCatchBlock.start); + int endIndex = insnList.indexOf(tryCatchBlock.end); + for (int j = startIndex; j < endIndex; ++j) { + List insnHandlers = handlers[j]; + if (insnHandlers == null) { + insnHandlers = new ArrayList(); + handlers[j] = insnHandlers; + } + insnHandlers.add(tryCatchBlock); + } + } + + // For each instruction, compute the subroutine to which it belongs. + // Follow the main 'subroutine', and collect the jsr instructions to nested subroutines. + Subroutine main = new Subroutine(null, method.maxLocals, null); + List jsrInsns = new ArrayList(); + findSubroutine(0, main, jsrInsns); + // Follow the nested subroutines, and collect their own nested subroutines, until all + // subroutines are found. + Map jsrSubroutines = new HashMap(); + while (!jsrInsns.isEmpty()) { + JumpInsnNode jsrInsn = (JumpInsnNode) jsrInsns.remove(0); + Subroutine subroutine = jsrSubroutines.get(jsrInsn.label); + if (subroutine == null) { + subroutine = new Subroutine(jsrInsn.label, method.maxLocals, jsrInsn); + jsrSubroutines.put(jsrInsn.label, subroutine); + findSubroutine(insnList.indexOf(jsrInsn.label), subroutine, jsrInsns); + } else { + subroutine.callers.add(jsrInsn); + } + } + // Clear the main 'subroutine', which is not a real subroutine (and was used only as an + // intermediate step above to find the real ones). + for (int i = 0; i < insnListSize; ++i) { + if (subroutines[i] != null && subroutines[i].start == null) { + subroutines[i] = null; + } + } + + // Initializes the data structures for the control flow analysis. + Frame currentFrame = computeInitialFrame(owner, method); + merge(0, currentFrame, null); + init(owner, method); + + // Control flow analysis. + while (numInstructionsToProcess > 0) { + // Get and remove one instruction from the list of instructions to process. + int insnIndex = instructionsToProcess[--numInstructionsToProcess]; + Frame oldFrame = frames[insnIndex]; + Subroutine subroutine = subroutines[insnIndex]; + inInstructionsToProcess[insnIndex] = false; + + // Simulate the execution of this instruction. + AbstractInsnNode insnNode = null; + try { + insnNode = method.instructions.get(insnIndex); + int insnOpcode = insnNode.getOpcode(); + int insnType = insnNode.getType(); + + if (insnType == AbstractInsnNode.LABEL + || insnType == AbstractInsnNode.LINE + || insnType == AbstractInsnNode.FRAME) { + merge(insnIndex + 1, oldFrame, subroutine); + newControlFlowEdge(insnIndex, insnIndex + 1); + } else { + currentFrame.init(oldFrame).execute(insnNode, interpreter); + subroutine = subroutine == null ? null : new Subroutine(subroutine); + + if (insnNode instanceof JumpInsnNode) { + JumpInsnNode jumpInsn = (JumpInsnNode) insnNode; + if (insnOpcode != GOTO && insnOpcode != JSR) { + merge(insnIndex + 1, currentFrame, subroutine); + newControlFlowEdge(insnIndex, insnIndex + 1); + } + int jumpInsnIndex = insnList.indexOf(jumpInsn.label); + if (insnOpcode == JSR) { + merge( + jumpInsnIndex, + currentFrame, + new Subroutine(jumpInsn.label, method.maxLocals, jumpInsn)); + } else { + merge(jumpInsnIndex, currentFrame, subroutine); + } + newControlFlowEdge(insnIndex, jumpInsnIndex); + } else if (insnNode instanceof LookupSwitchInsnNode) { + LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) insnNode; + int targetInsnIndex = insnList.indexOf(lookupSwitchInsn.dflt); + merge(targetInsnIndex, currentFrame, subroutine); + newControlFlowEdge(insnIndex, targetInsnIndex); + for (int i = 0; i < lookupSwitchInsn.labels.size(); ++i) { + targetInsnIndex = insnList.indexOf(lookupSwitchInsn.labels.get(i)); + merge(targetInsnIndex, currentFrame, subroutine); + newControlFlowEdge(insnIndex, targetInsnIndex); + } + } else if (insnNode instanceof TableSwitchInsnNode) { + TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) insnNode; + int targetInsnIndex = insnList.indexOf(tableSwitchInsn.dflt); + merge(targetInsnIndex, currentFrame, subroutine); + newControlFlowEdge(insnIndex, targetInsnIndex); + for (int i = 0; i < tableSwitchInsn.labels.size(); ++i) { + targetInsnIndex = insnList.indexOf(tableSwitchInsn.labels.get(i)); + merge(targetInsnIndex, currentFrame, subroutine); + newControlFlowEdge(insnIndex, targetInsnIndex); + } + } else if (insnOpcode == RET) { + if (subroutine == null) { + throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine"); + } + for (int i = 0; i < subroutine.callers.size(); ++i) { + JumpInsnNode caller = subroutine.callers.get(i); + int jsrInsnIndex = insnList.indexOf(caller); + if (frames[jsrInsnIndex] != null) { + merge( + jsrInsnIndex + 1, + frames[jsrInsnIndex], + currentFrame, + subroutines[jsrInsnIndex], + subroutine.localsUsed); + newControlFlowEdge(insnIndex, jsrInsnIndex + 1); + } + } + } else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) { + if (subroutine != null) { + if (insnNode instanceof VarInsnNode) { + int var = ((VarInsnNode) insnNode).var; + subroutine.localsUsed[var] = true; + if (insnOpcode == LLOAD + || insnOpcode == DLOAD + || insnOpcode == LSTORE + || insnOpcode == DSTORE) { + subroutine.localsUsed[var + 1] = true; + } + } else if (insnNode instanceof IincInsnNode) { + int var = ((IincInsnNode) insnNode).var; + subroutine.localsUsed[var] = true; + } + } + merge(insnIndex + 1, currentFrame, subroutine); + newControlFlowEdge(insnIndex, insnIndex + 1); + } + } + + List insnHandlers = handlers[insnIndex]; + if (insnHandlers != null) { + for (int i = 0; i < insnHandlers.size(); ++i) { + TryCatchBlockNode tryCatchBlock = insnHandlers.get(i); + Type catchType; + if (tryCatchBlock.type == null) { + catchType = Type.getObjectType("java/lang/Throwable"); + } else { + catchType = Type.getObjectType(tryCatchBlock.type); + } + if (newControlFlowExceptionEdge(insnIndex, tryCatchBlock)) { + Frame handler = newFrame(oldFrame); + handler.clearStack(); + handler.push(interpreter.newValue(catchType)); + merge(insnList.indexOf(tryCatchBlock.handler), handler, subroutine); + } + } + } + } catch (AnalyzerException e) { + throw new AnalyzerException( + e.node, "Error at instruction " + insnIndex + ": " + e.getMessage(), e); + } catch (Exception e) { + throw new AnalyzerException( + insnNode, "Error at instruction " + insnIndex + ": " + e.getMessage(), e); + } + } + + return frames; + } + + /** + * Follows the control flow graph of the currently analyzed method, starting at the given + * instruction index, and stores a copy of the given subroutine in {@link #subroutines} for each + * encountered instruction. Jumps to nested subroutines are not followed: instead, the + * corresponding instructions are put in the given list. + * + * @param insnIndex an instruction index. + * @param subroutine a subroutine. + * @param jsrInsns where the jsr instructions for nested subroutines must be put. + * @throws AnalyzerException if the control flow graph can fall off the end of the code. + */ + private void findSubroutine( + final int insnIndex, final Subroutine subroutine, final List jsrInsns) + throws AnalyzerException { + int currentInsnIndex = insnIndex; + while (true) { + if (currentInsnIndex < 0 || currentInsnIndex >= insnListSize) { + throw new AnalyzerException(null, "Execution can fall off the end of the code"); + } + if (subroutines[currentInsnIndex] != null) { + return; + } + subroutines[currentInsnIndex] = new Subroutine(subroutine); + AbstractInsnNode currentInsn = insnList.get(currentInsnIndex); + + // Call findSubroutine recursively on the normal successors of currentInsn. + if (currentInsn instanceof JumpInsnNode) { + if (currentInsn.getOpcode() == JSR) { + // Do not follow a jsr, it leads to another subroutine! + jsrInsns.add(currentInsn); + } else { + JumpInsnNode jumpInsn = (JumpInsnNode) currentInsn; + findSubroutine(insnList.indexOf(jumpInsn.label), subroutine, jsrInsns); + } + } else if (currentInsn instanceof TableSwitchInsnNode) { + TableSwitchInsnNode tableSwitchInsn = (TableSwitchInsnNode) currentInsn; + findSubroutine(insnList.indexOf(tableSwitchInsn.dflt), subroutine, jsrInsns); + for (int i = tableSwitchInsn.labels.size() - 1; i >= 0; --i) { + LabelNode l = tableSwitchInsn.labels.get(i); + findSubroutine(insnList.indexOf(l), subroutine, jsrInsns); + } + } else if (currentInsn instanceof LookupSwitchInsnNode) { + LookupSwitchInsnNode lookupSwitchInsn = (LookupSwitchInsnNode) currentInsn; + findSubroutine(insnList.indexOf(lookupSwitchInsn.dflt), subroutine, jsrInsns); + for (int i = lookupSwitchInsn.labels.size() - 1; i >= 0; --i) { + LabelNode l = lookupSwitchInsn.labels.get(i); + findSubroutine(insnList.indexOf(l), subroutine, jsrInsns); + } + } + + // Call findSubroutine recursively on the exception handler successors of currentInsn. + List insnHandlers = handlers[currentInsnIndex]; + if (insnHandlers != null) { + for (int i = 0; i < insnHandlers.size(); ++i) { + TryCatchBlockNode tryCatchBlock = insnHandlers.get(i); + findSubroutine(insnList.indexOf(tryCatchBlock.handler), subroutine, jsrInsns); + } + } + + // If currentInsn does not fall through to the next instruction, return. + switch (currentInsn.getOpcode()) { + case GOTO: + case RET: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case LRETURN: + case FRETURN: + case DRETURN: + case ARETURN: + case RETURN: + case ATHROW: + return; + default: + break; + } + currentInsnIndex++; + } + } + + /** + * Computes the initial execution stack frame of the given method. + * + * @param owner the internal name of the class to which 'method' belongs. + * @param method the method to be analyzed. + * @return the initial execution stack frame of the 'method'. + */ + private Frame computeInitialFrame(final String owner, final MethodNode method) { + Frame frame = newFrame(method.maxLocals, method.maxStack); + int currentLocal = 0; + if ((method.access & ACC_STATIC) == 0) { + Type ownerType = Type.getObjectType(owner); + frame.setLocal(currentLocal++, interpreter.newValue(ownerType)); + } + Type[] argumentTypes = Type.getArgumentTypes(method.desc); + for (int i = 0; i < argumentTypes.length; ++i) { + frame.setLocal(currentLocal++, interpreter.newValue(argumentTypes[i])); + if (argumentTypes[i].getSize() == 2) { + frame.setLocal(currentLocal++, interpreter.newValue(null)); + } + } + while (currentLocal < method.maxLocals) { + frame.setLocal(currentLocal++, interpreter.newValue(null)); + } + frame.setReturn(interpreter.newValue(Type.getReturnType(method.desc))); + return frame; + } + + /** + * Returns the symbolic execution stack frame for each instruction of the last analyzed method. + * + * @return the symbolic state of the execution stack frame at each bytecode instruction of the + * method. The size of the returned array is equal to the number of instructions (and labels) + * of the method. A given frame is null if the corresponding instruction cannot be + * reached, or if an error occurred during the analysis of the method. + */ + public Frame[] getFrames() { + return frames; + } + + /** + * Returns the exception handlers for the given instruction. + * + * @param insnIndex the index of an instruction of the last analyzed method. + * @return a list of {@link TryCatchBlockNode} objects. + */ + public List getHandlers(final int insnIndex) { + return handlers[insnIndex]; + } + + /** + * Initializes this analyzer. This method is called just before the execution of control flow + * analysis loop in #analyze. The default implementation of this method does nothing. + * + * @param owner the internal name of the class to which the method belongs. + * @param method the method to be analyzed. + * @throws AnalyzerException if a problem occurs. + */ + protected void init(final String owner, final MethodNode method) throws AnalyzerException { + // Nothing to do. + } + + /** + * Constructs a new frame with the given size. + * + * @param nLocals the maximum number of local variables of the frame. + * @param nStack the maximum stack size of the frame. + * @return the created frame. + */ + protected Frame newFrame(final int nLocals, final int nStack) { + return new Frame(nLocals, nStack); + } + + /** + * Constructs a copy of the given frame. + * + * @param frame a frame. + * @return the created frame. + */ + protected Frame newFrame(final Frame frame) { + return new Frame(frame); + } + + /** + * Creates a control flow graph edge. The default implementation of this method does nothing. It + * can be overridden in order to construct the control flow graph of a method (this method is + * called by the {@link #analyze} method during its visit of the method's code). + * + * @param insnIndex an instruction index. + * @param successorIndex index of a successor instruction. + */ + protected void newControlFlowEdge(final int insnIndex, final int successorIndex) { + // Nothing to do. + } + + /** + * Creates a control flow graph edge corresponding to an exception handler. The default + * implementation of this method does nothing. It can be overridden in order to construct the + * control flow graph of a method (this method is called by the {@link #analyze} method during its + * visit of the method's code). + * + * @param insnIndex an instruction index. + * @param successorIndex index of a successor instruction. + * @return true if this edge must be considered in the data flow analysis performed by this + * analyzer, or false otherwise. The default implementation of this method always returns + * true. + */ + protected boolean newControlFlowExceptionEdge(final int insnIndex, final int successorIndex) { + return true; + } + + /** + * Creates a control flow graph edge corresponding to an exception handler. The default + * implementation of this method delegates to {@link #newControlFlowExceptionEdge(int, int)}. It + * can be overridden in order to construct the control flow graph of a method (this method is + * called by the {@link #analyze} method during its visit of the method's code). + * + * @param insnIndex an instruction index. + * @param tryCatchBlock TryCatchBlockNode corresponding to this edge. + * @return true if this edge must be considered in the data flow analysis performed by this + * analyzer, or false otherwise. The default implementation of this method delegates to {@link + * #newControlFlowExceptionEdge(int, int)}. + */ + protected boolean newControlFlowExceptionEdge( + final int insnIndex, final TryCatchBlockNode tryCatchBlock) { + return newControlFlowExceptionEdge(insnIndex, insnList.indexOf(tryCatchBlock.handler)); + } + + // ----------------------------------------------------------------------------------------------- + + /** + * Merges the given frame and subroutine into the frame and subroutines at the given instruction + * index. If the frame or the subroutine at the given instruction index changes as a result of + * this merge, the instruction index is added to the list of instructions to process (if it is not + * already the case). + * + * @param insnIndex an instruction index. + * @param frame a frame. This frame is left unchanged by this method. + * @param subroutine a subroutine. This subroutine is left unchanged by this method. + * @throws AnalyzerException if the frames have incompatible sizes. + */ + private void merge(final int insnIndex, final Frame frame, final Subroutine subroutine) + throws AnalyzerException { + boolean changed; + Frame oldFrame = frames[insnIndex]; + if (oldFrame == null) { + frames[insnIndex] = newFrame(frame); + changed = true; + } else { + changed = oldFrame.merge(frame, interpreter); + } + Subroutine oldSubroutine = subroutines[insnIndex]; + if (oldSubroutine == null) { + if (subroutine != null) { + subroutines[insnIndex] = new Subroutine(subroutine); + changed = true; + } + } else { + if (subroutine != null) { + changed |= oldSubroutine.merge(subroutine); + } + } + if (changed && !inInstructionsToProcess[insnIndex]) { + inInstructionsToProcess[insnIndex] = true; + instructionsToProcess[numInstructionsToProcess++] = insnIndex; + } + } + + /** + * Merges the given frame and subroutine into the frame and subroutines at the given instruction + * index (case of a RET instruction). If the frame or the subroutine at the given instruction + * index changes as a result of this merge, the instruction index is added to the list of + * instructions to process (if it is not already the case). + * + * @param insnIndex the index of an instruction immediately following a jsr instruction. + * @param frameBeforeJsr the execution stack frame before the jsr instruction. This frame is + * merged into 'frameAfterRet'. + * @param frameAfterRet the execution stack frame after a ret instruction of the subroutine. This + * frame is merged into the frame at 'insnIndex' (after it has itself been merge with + * 'frameBeforeJsr'). + * @param subroutineBeforeJsr if the jsr is itself part of a subroutine (case of nested + * subroutine), the subroutine it belongs to. + * @param localsUsed the local variables read or written in the subroutine. + * @throws AnalyzerException if the frames have incompatible sizes. + */ + private void merge( + final int insnIndex, + final Frame frameBeforeJsr, + final Frame frameAfterRet, + final Subroutine subroutineBeforeJsr, + final boolean[] localsUsed) + throws AnalyzerException { + frameAfterRet.merge(frameBeforeJsr, localsUsed); + + boolean changed; + Frame oldFrame = frames[insnIndex]; + if (oldFrame == null) { + frames[insnIndex] = newFrame(frameAfterRet); + changed = true; + } else { + changed = oldFrame.merge(frameAfterRet, interpreter); + } + Subroutine oldSubroutine = subroutines[insnIndex]; + if (oldSubroutine != null && subroutineBeforeJsr != null) { + changed |= oldSubroutine.merge(subroutineBeforeJsr); + } + if (changed && !inInstructionsToProcess[insnIndex]) { + inInstructionsToProcess[insnIndex] = true; + instructionsToProcess[numInstructionsToProcess++] = insnIndex; + } + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/AnalyzerException.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/AnalyzerException.java new file mode 100644 index 000000000..11f4ffab9 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/AnalyzerException.java @@ -0,0 +1,89 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import org.objectweb.asm.tree.AbstractInsnNode; + +/** + * An exception thrown if a problem occurs during the analysis of a method. + * + * @author Bing Ran + * @author Eric Bruneton + */ +public class AnalyzerException extends Exception { + + private static final long serialVersionUID = 3154190448018943333L; + + /** The bytecode instruction where the analysis failed. */ + public final transient AbstractInsnNode node; + + /** + * Constructs a new {@link AnalyzerException}. + * + * @param insn the bytecode instruction where the analysis failed. + * @param message the reason why the analysis failed. + */ + public AnalyzerException(final AbstractInsnNode insn, final String message) { + super(message); + this.node = insn; + } + + /** + * Constructs a new {@link AnalyzerException}. + * + * @param insn the bytecode instruction where the analysis failed. + * @param message the reason why the analysis failed. + * @param cause the cause of the failure. + */ + public AnalyzerException( + final AbstractInsnNode insn, final String message, final Throwable cause) { + super(message, cause); + this.node = insn; + } + + /** + * Constructs a new {@link AnalyzerException}. + * + * @param insn the bytecode instruction where the analysis failed. + * @param message the reason why the analysis failed. + * @param expected an expected value. + * @param actual the actual value, different from the expected one. + */ + public AnalyzerException( + final AbstractInsnNode insn, + final String message, + final Object expected, + final Value actual) { + super( + (message == null ? "Expected " : message + ": expected ") + + expected + + ", but found " + + actual); + this.node = insn; + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java new file mode 100644 index 000000000..bebd8d848 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicInterpreter.java @@ -0,0 +1,377 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.List; + +import org.objectweb.asm.ConstantDynamic; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.IntInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.TypeInsnNode; + +/** + * An {@link Interpreter} for {@link BasicValue} values. + * + * @author Eric Bruneton + * @author Bing Ran + */ +public class BasicInterpreter extends Interpreter implements Opcodes { + + /** + * Special type used for the null literal. This is an object reference type with + * descriptor 'Lnull;'. + */ + public static final Type NULL_TYPE = Type.getObjectType("null"); + + /** + * Constructs a new {@link BasicInterpreter} for the latest ASM API version. Subclasses must + * not use this constructor. Instead, they must use the {@link #BasicInterpreter(int)} + * version. + */ + public BasicInterpreter() { + super(ASM6); + if (getClass() != BasicInterpreter.class) { + throw new IllegalStateException(); + } + } + + /** + * Constructs a new {@link BasicInterpreter}. + * + * @param api the ASM API version supported by this interpreter. Must be one of {@link + * org.objectweb.asm.Opcodes#ASM4}, {@link org.objectweb.asm.Opcodes#ASM5}, {@link + * org.objectweb.asm.Opcodes#ASM6} or {@link org.objectweb.asm.Opcodes#ASM7_EXPERIMENTAL}. + */ + protected BasicInterpreter(final int api) { + super(api); + } + + @Override + public BasicValue newValue(final Type type) { + if (type == null) { + return BasicValue.UNINITIALIZED_VALUE; + } + switch (type.getSort()) { + case Type.VOID: + return null; + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + return BasicValue.INT_VALUE; + case Type.FLOAT: + return BasicValue.FLOAT_VALUE; + case Type.LONG: + return BasicValue.LONG_VALUE; + case Type.DOUBLE: + return BasicValue.DOUBLE_VALUE; + case Type.ARRAY: + case Type.OBJECT: + return BasicValue.REFERENCE_VALUE; + default: + throw new AssertionError(); + } + } + + @Override + public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException { + switch (insn.getOpcode()) { + case ACONST_NULL: + return newValue(NULL_TYPE); + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + return BasicValue.INT_VALUE; + case LCONST_0: + case LCONST_1: + return BasicValue.LONG_VALUE; + case FCONST_0: + case FCONST_1: + case FCONST_2: + return BasicValue.FLOAT_VALUE; + case DCONST_0: + case DCONST_1: + return BasicValue.DOUBLE_VALUE; + case BIPUSH: + case SIPUSH: + return BasicValue.INT_VALUE; + case LDC: + Object value = ((LdcInsnNode) insn).cst; + if (value instanceof Integer) { + return BasicValue.INT_VALUE; + } else if (value instanceof Float) { + return BasicValue.FLOAT_VALUE; + } else if (value instanceof Long) { + return BasicValue.LONG_VALUE; + } else if (value instanceof Double) { + return BasicValue.DOUBLE_VALUE; + } else if (value instanceof String) { + return newValue(Type.getObjectType("java/lang/String")); + } else if (value instanceof Type) { + int sort = ((Type) value).getSort(); + if (sort == Type.OBJECT || sort == Type.ARRAY) { + return newValue(Type.getObjectType("java/lang/Class")); + } else if (sort == Type.METHOD) { + return newValue(Type.getObjectType("java/lang/invoke/MethodType")); + } else { + throw new AnalyzerException(insn, "Illegal LDC value " + value); + } + } else if (value instanceof Handle) { + return newValue(Type.getObjectType("java/lang/invoke/MethodHandle")); + } else if (value instanceof ConstantDynamic) { + return newValue(Type.getType(((ConstantDynamic)value).getDescriptor())); + } else { + throw new AnalyzerException(insn, "Illegal LDC value " + value); + } + case JSR: + return BasicValue.RETURNADDRESS_VALUE; + case GETSTATIC: + return newValue(Type.getType(((FieldInsnNode) insn).desc)); + case NEW: + return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); + default: + throw new AssertionError(); + } + } + + @Override + public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value) + throws AnalyzerException { + return value; + } + + @Override + public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value) + throws AnalyzerException { + switch (insn.getOpcode()) { + case INEG: + case IINC: + case L2I: + case F2I: + case D2I: + case I2B: + case I2C: + case I2S: + return BasicValue.INT_VALUE; + case FNEG: + case I2F: + case L2F: + case D2F: + return BasicValue.FLOAT_VALUE; + case LNEG: + case I2L: + case F2L: + case D2L: + return BasicValue.LONG_VALUE; + case DNEG: + case I2D: + case L2D: + case F2D: + return BasicValue.DOUBLE_VALUE; + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case LRETURN: + case FRETURN: + case DRETURN: + case ARETURN: + case PUTSTATIC: + return null; + case GETFIELD: + return newValue(Type.getType(((FieldInsnNode) insn).desc)); + case NEWARRAY: + switch (((IntInsnNode) insn).operand) { + case T_BOOLEAN: + return newValue(Type.getType("[Z")); + case T_CHAR: + return newValue(Type.getType("[C")); + case T_BYTE: + return newValue(Type.getType("[B")); + case T_SHORT: + return newValue(Type.getType("[S")); + case T_INT: + return newValue(Type.getType("[I")); + case T_FLOAT: + return newValue(Type.getType("[F")); + case T_DOUBLE: + return newValue(Type.getType("[D")); + case T_LONG: + return newValue(Type.getType("[J")); + default: + break; + } + throw new AnalyzerException(insn, "Invalid array type"); + case ANEWARRAY: + return newValue(Type.getType("[" + Type.getObjectType(((TypeInsnNode) insn).desc))); + case ARRAYLENGTH: + return BasicValue.INT_VALUE; + case ATHROW: + return null; + case CHECKCAST: + return newValue(Type.getObjectType(((TypeInsnNode) insn).desc)); + case INSTANCEOF: + return BasicValue.INT_VALUE; + case MONITORENTER: + case MONITOREXIT: + case IFNULL: + case IFNONNULL: + return null; + default: + throw new AssertionError(); + } + } + + @Override + public BasicValue binaryOperation( + final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2) + throws AnalyzerException { + switch (insn.getOpcode()) { + case IALOAD: + case BALOAD: + case CALOAD: + case SALOAD: + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + return BasicValue.INT_VALUE; + case FALOAD: + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + return BasicValue.FLOAT_VALUE; + case LALOAD: + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + return BasicValue.LONG_VALUE; + case DALOAD: + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + return BasicValue.DOUBLE_VALUE; + case AALOAD: + return BasicValue.REFERENCE_VALUE; + case LCMP: + case FCMPL: + case FCMPG: + case DCMPL: + case DCMPG: + return BasicValue.INT_VALUE; + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + case PUTFIELD: + return null; + default: + throw new AssertionError(); + } + } + + @Override + public BasicValue ternaryOperation( + final AbstractInsnNode insn, + final BasicValue value1, + final BasicValue value2, + final BasicValue value3) + throws AnalyzerException { + return null; + } + + @Override + public BasicValue naryOperation( + final AbstractInsnNode insn, final List values) + throws AnalyzerException { + int opcode = insn.getOpcode(); + if (opcode == MULTIANEWARRAY) { + return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc)); + } else if (opcode == INVOKEDYNAMIC) { + return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc)); + } else { + return newValue(Type.getReturnType(((MethodInsnNode) insn).desc)); + } + } + + @Override + public void returnOperation( + final AbstractInsnNode insn, final BasicValue value, final BasicValue expected) + throws AnalyzerException { + // Nothing to do. + } + + @Override + public BasicValue merge(final BasicValue value1, final BasicValue value2) { + if (!value1.equals(value2)) { + return BasicValue.UNINITIALIZED_VALUE; + } + return value1; + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicValue.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicValue.java new file mode 100644 index 000000000..461eea657 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicValue.java @@ -0,0 +1,128 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import org.objectweb.asm.Type; + +/** + * A {@link Value} that is represented with its type in a seven types type system. This type system + * distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types. + * + * @author Eric Bruneton + */ +public class BasicValue implements Value { + + /** An uninitialized value. */ + public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null); + + /** A byte, boolean, char, short, or int value. */ + public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE); + + /** A float value. */ + public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE); + + /** A long value. */ + public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE); + + /** A double value. */ + public static final BasicValue DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE); + + /** An object or array reference value. */ + public static final BasicValue REFERENCE_VALUE = + new BasicValue(Type.getObjectType("java/lang/Object")); + + /** A return address value (produced by a jsr instruction). */ + public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(Type.VOID_TYPE); + + /** The {@link Type} of this value, or null for uninitialized values. */ + private final Type type; + + /** + * Constructs a new {@link BasicValue} of the given type. + * + * @param type the value type. + */ + public BasicValue(final Type type) { + this.type = type; + } + + /** + * Returns the {@link Type} of this value. + * + * @return the {@link Type} of this value. + */ + public Type getType() { + return type; + } + + public int getSize() { + return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1; + } + + /** + * Returns whether this value corresponds to an object or array reference. + * + * @return whether this value corresponds to an object or array reference. + */ + public boolean isReference() { + return type != null && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY); + } + + @Override + public boolean equals(final Object value) { + if (value == this) { + return true; + } else if (value instanceof BasicValue) { + if (type == null) { + return ((BasicValue) value).type == null; + } else { + return type.equals(((BasicValue) value).type); + } + } else { + return false; + } + } + + @Override + public int hashCode() { + return type == null ? 0 : type.hashCode(); + } + + @Override + public String toString() { + if (this == UNINITIALIZED_VALUE) { + return "."; + } else if (this == RETURNADDRESS_VALUE) { + return "A"; + } else if (this == REFERENCE_VALUE) { + return "R"; + } else { + return type.getDescriptor(); + } + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicVerifier.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicVerifier.java new file mode 100644 index 000000000..a8575abdf --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/BasicVerifier.java @@ -0,0 +1,451 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.List; + +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; + +/** + * An extended {@link BasicInterpreter} that checks that bytecode instructions are correctly used. + * + * @author Eric Bruneton + * @author Bing Ran + */ +public class BasicVerifier extends BasicInterpreter { + + /** + * Constructs a new {@link BasicVerifier} for the latest ASM API version. Subclasses must not + * use this constructor. Instead, they must use the {@link #BasicVerifier(int)} version. + */ + public BasicVerifier() { + super(ASM6); + if (getClass() != BasicVerifier.class) { + throw new IllegalStateException(); + } + } + + /** + * Constructs a new {@link BasicVerifier}. + * + * @param api the ASM API version supported by this interpreter. Must be one of {@link + * org.objectweb.asm.Opcodes#ASM4}, {@link org.objectweb.asm.Opcodes#ASM5}, {@link + * org.objectweb.asm.Opcodes#ASM6} or {@link org.objectweb.asm.Opcodes#ASM7_EXPERIMENTAL}. + */ + protected BasicVerifier(final int api) { + super(api); + } + + @Override + public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value) + throws AnalyzerException { + Value expected; + switch (insn.getOpcode()) { + case ILOAD: + case ISTORE: + expected = BasicValue.INT_VALUE; + break; + case FLOAD: + case FSTORE: + expected = BasicValue.FLOAT_VALUE; + break; + case LLOAD: + case LSTORE: + expected = BasicValue.LONG_VALUE; + break; + case DLOAD: + case DSTORE: + expected = BasicValue.DOUBLE_VALUE; + break; + case ALOAD: + if (!value.isReference()) { + throw new AnalyzerException(insn, null, "an object reference", value); + } + return value; + case ASTORE: + if (!value.isReference() && !BasicValue.RETURNADDRESS_VALUE.equals(value)) { + throw new AnalyzerException(insn, null, "an object reference or a return address", value); + } + return value; + default: + return value; + } + if (!expected.equals(value)) { + throw new AnalyzerException(insn, null, expected, value); + } + return value; + } + + @Override + public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value) + throws AnalyzerException { + BasicValue expected; + switch (insn.getOpcode()) { + case INEG: + case IINC: + case I2F: + case I2L: + case I2D: + case I2B: + case I2C: + case I2S: + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case TABLESWITCH: + case LOOKUPSWITCH: + case IRETURN: + case NEWARRAY: + case ANEWARRAY: + expected = BasicValue.INT_VALUE; + break; + case FNEG: + case F2I: + case F2L: + case F2D: + case FRETURN: + expected = BasicValue.FLOAT_VALUE; + break; + case LNEG: + case L2I: + case L2F: + case L2D: + case LRETURN: + expected = BasicValue.LONG_VALUE; + break; + case DNEG: + case D2I: + case D2F: + case D2L: + case DRETURN: + expected = BasicValue.DOUBLE_VALUE; + break; + case GETFIELD: + expected = newValue(Type.getObjectType(((FieldInsnNode) insn).owner)); + break; + case ARRAYLENGTH: + if (!isArrayValue(value)) { + throw new AnalyzerException(insn, null, "an array reference", value); + } + return super.unaryOperation(insn, value); + case CHECKCAST: + case ARETURN: + case ATHROW: + case INSTANCEOF: + case MONITORENTER: + case MONITOREXIT: + case IFNULL: + case IFNONNULL: + if (!value.isReference()) { + throw new AnalyzerException(insn, null, "an object reference", value); + } + return super.unaryOperation(insn, value); + case PUTSTATIC: + expected = newValue(Type.getType(((FieldInsnNode) insn).desc)); + break; + default: + throw new AssertionError(); + } + if (!isSubTypeOf(value, expected)) { + throw new AnalyzerException(insn, null, expected, value); + } + return super.unaryOperation(insn, value); + } + + @Override + public BasicValue binaryOperation( + final AbstractInsnNode insn, final BasicValue value1, final BasicValue value2) + throws AnalyzerException { + BasicValue expected1; + BasicValue expected2; + switch (insn.getOpcode()) { + case IALOAD: + expected1 = newValue(Type.getType("[I")); + expected2 = BasicValue.INT_VALUE; + break; + case BALOAD: + if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { + expected1 = newValue(Type.getType("[Z")); + } else { + expected1 = newValue(Type.getType("[B")); + } + expected2 = BasicValue.INT_VALUE; + break; + case CALOAD: + expected1 = newValue(Type.getType("[C")); + expected2 = BasicValue.INT_VALUE; + break; + case SALOAD: + expected1 = newValue(Type.getType("[S")); + expected2 = BasicValue.INT_VALUE; + break; + case LALOAD: + expected1 = newValue(Type.getType("[J")); + expected2 = BasicValue.INT_VALUE; + break; + case FALOAD: + expected1 = newValue(Type.getType("[F")); + expected2 = BasicValue.INT_VALUE; + break; + case DALOAD: + expected1 = newValue(Type.getType("[D")); + expected2 = BasicValue.INT_VALUE; + break; + case AALOAD: + expected1 = newValue(Type.getType("[Ljava/lang/Object;")); + expected2 = BasicValue.INT_VALUE; + break; + case IADD: + case ISUB: + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + expected1 = BasicValue.INT_VALUE; + expected2 = BasicValue.INT_VALUE; + break; + case FADD: + case FSUB: + case FMUL: + case FDIV: + case FREM: + case FCMPL: + case FCMPG: + expected1 = BasicValue.FLOAT_VALUE; + expected2 = BasicValue.FLOAT_VALUE; + break; + case LADD: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LAND: + case LOR: + case LXOR: + case LCMP: + expected1 = BasicValue.LONG_VALUE; + expected2 = BasicValue.LONG_VALUE; + break; + case LSHL: + case LSHR: + case LUSHR: + expected1 = BasicValue.LONG_VALUE; + expected2 = BasicValue.INT_VALUE; + break; + case DADD: + case DSUB: + case DMUL: + case DDIV: + case DREM: + case DCMPL: + case DCMPG: + expected1 = BasicValue.DOUBLE_VALUE; + expected2 = BasicValue.DOUBLE_VALUE; + break; + case IF_ACMPEQ: + case IF_ACMPNE: + expected1 = BasicValue.REFERENCE_VALUE; + expected2 = BasicValue.REFERENCE_VALUE; + break; + case PUTFIELD: + FieldInsnNode fieldInsn = (FieldInsnNode) insn; + expected1 = newValue(Type.getObjectType(fieldInsn.owner)); + expected2 = newValue(Type.getType(fieldInsn.desc)); + break; + default: + throw new AssertionError(); + } + if (!isSubTypeOf(value1, expected1)) { + throw new AnalyzerException(insn, "First argument", expected1, value1); + } else if (!isSubTypeOf(value2, expected2)) { + throw new AnalyzerException(insn, "Second argument", expected2, value2); + } + if (insn.getOpcode() == AALOAD) { + return getElementValue(value1); + } else { + return super.binaryOperation(insn, value1, value2); + } + } + + @Override + public BasicValue ternaryOperation( + final AbstractInsnNode insn, + final BasicValue value1, + final BasicValue value2, + final BasicValue value3) + throws AnalyzerException { + BasicValue expected1; + BasicValue expected3; + switch (insn.getOpcode()) { + case IASTORE: + expected1 = newValue(Type.getType("[I")); + expected3 = BasicValue.INT_VALUE; + break; + case BASTORE: + if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) { + expected1 = newValue(Type.getType("[Z")); + } else { + expected1 = newValue(Type.getType("[B")); + } + expected3 = BasicValue.INT_VALUE; + break; + case CASTORE: + expected1 = newValue(Type.getType("[C")); + expected3 = BasicValue.INT_VALUE; + break; + case SASTORE: + expected1 = newValue(Type.getType("[S")); + expected3 = BasicValue.INT_VALUE; + break; + case LASTORE: + expected1 = newValue(Type.getType("[J")); + expected3 = BasicValue.LONG_VALUE; + break; + case FASTORE: + expected1 = newValue(Type.getType("[F")); + expected3 = BasicValue.FLOAT_VALUE; + break; + case DASTORE: + expected1 = newValue(Type.getType("[D")); + expected3 = BasicValue.DOUBLE_VALUE; + break; + case AASTORE: + expected1 = value1; + expected3 = BasicValue.REFERENCE_VALUE; + break; + default: + throw new AssertionError(); + } + if (!isSubTypeOf(value1, expected1)) { + throw new AnalyzerException( + insn, "First argument", "a " + expected1 + " array reference", value1); + } else if (!BasicValue.INT_VALUE.equals(value2)) { + throw new AnalyzerException(insn, "Second argument", BasicValue.INT_VALUE, value2); + } else if (!isSubTypeOf(value3, expected3)) { + throw new AnalyzerException(insn, "Third argument", expected3, value3); + } + return null; + } + + @Override + public BasicValue naryOperation( + final AbstractInsnNode insn, final List values) + throws AnalyzerException { + int opcode = insn.getOpcode(); + if (opcode == MULTIANEWARRAY) { + for (int i = 0; i < values.size(); ++i) { + if (!BasicValue.INT_VALUE.equals(values.get(i))) { + throw new AnalyzerException(insn, null, BasicValue.INT_VALUE, values.get(i)); + } + } + } else { + int i = 0; + int j = 0; + if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) { + Type owner = Type.getObjectType(((MethodInsnNode) insn).owner); + if (!isSubTypeOf(values.get(i++), newValue(owner))) { + throw new AnalyzerException(insn, "Method owner", newValue(owner), values.get(0)); + } + } + String methodDescriptor = + (opcode == INVOKEDYNAMIC) + ? ((InvokeDynamicInsnNode) insn).desc + : ((MethodInsnNode) insn).desc; + Type[] args = Type.getArgumentTypes(methodDescriptor); + while (i < values.size()) { + BasicValue expected = newValue(args[j++]); + BasicValue actual = values.get(i++); + if (!isSubTypeOf(actual, expected)) { + throw new AnalyzerException(insn, "Argument " + j, expected, actual); + } + } + } + return super.naryOperation(insn, values); + } + + @Override + public void returnOperation( + final AbstractInsnNode insn, final BasicValue value, final BasicValue expected) + throws AnalyzerException { + if (!isSubTypeOf(value, expected)) { + throw new AnalyzerException(insn, "Incompatible return type", expected, value); + } + } + + /** + * Returns whether the given value corresponds to an array reference. + * + * @param value a value. + * @return whether 'value' corresponds to an array reference. + */ + protected boolean isArrayValue(final BasicValue value) { + return value.isReference(); + } + + /** + * Returns the value corresponding to the type of the elements of the given array reference value. + * + * @param objectArrayValue a value corresponding to array of object (or array) references. + * @return the value corresponding to the type of the elements of 'objectArrayValue'. + * @throws AnalyzerException if objectArrayValue does not correspond to an array type. + */ + protected BasicValue getElementValue(final BasicValue objectArrayValue) throws AnalyzerException { + return BasicValue.REFERENCE_VALUE; + } + + /** + * Returns whether the type corresponding to the first argument is a subtype of the type + * corresponding to the second argument. + * + * @param value a value. + * @param expected another value. + * @return whether the type corresponding to 'value' is a subtype of the type corresponding to + * 'expected'. + */ + protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) { + return value.equals(expected); + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java new file mode 100644 index 000000000..a3dd6c868 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Frame.java @@ -0,0 +1,699 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.ArrayList; +import java.util.List; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.IincInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MultiANewArrayInsnNode; +import org.objectweb.asm.tree.VarInsnNode; + +/** + * A symbolic execution stack frame. A stack frame contains a set of local variable slots, and an + * operand stack. Warning: long and double values are represented with two slots in local + * variables, and with one slot in the operand stack. + * + * @param type of the Value used for the analysis. + * @author Eric Bruneton + */ +public class Frame { + + /** + * The expected return type of the analyzed method, or null if the method returns void. + */ + private V returnValue; + + /** + * The local variables and the operand stack of this frame. The first {@link #nLocals} elements + * correspond to the local variables. The following {@link #nStack} elements correspond to the + * operand stack. + */ + private V[] values; + + /** The number of local variables of this frame. */ + private int nLocals; + + /** The number of elements in the operand stack. */ + private int nStack; + + /** + * Constructs a new frame with the given size. + * + * @param nLocals the maximum number of local variables of the frame. + * @param nStack the maximum stack size of the frame. + */ + @SuppressWarnings("unchecked") + public Frame(final int nLocals, final int nStack) { + this.values = (V[]) new Value[nLocals + nStack]; + this.nLocals = nLocals; + } + + /** + * Constructs a copy of the given. + * + * @param frame a frame. + */ + public Frame(final Frame frame) { + this(frame.nLocals, frame.values.length - frame.nLocals); + init(frame); + } + + /** + * Copies the state of the given frame into this frame. + * + * @param frame a frame. + * @return this frame. + */ + public Frame init(final Frame frame) { + returnValue = frame.returnValue; + System.arraycopy(frame.values, 0, values, 0, values.length); + nStack = frame.nStack; + return this; + } + + /** + * Sets the expected return type of the analyzed method. + * + * @param v the expected return type of the analyzed method, or null if the method + * returns void. + */ + public void setReturn(final V v) { + returnValue = v; + } + + /** + * Returns the maximum number of local variables of this frame. + * + * @return the maximum number of local variables of this frame. + */ + public int getLocals() { + return nLocals; + } + + /** + * Returns the maximum stack size of this frame. + * + * @return the maximum stack size of this frame. + */ + public int getMaxStackSize() { + return values.length - nLocals; + } + + /** + * Returns the value of the given local variable. + * + * @param index a local variable index. + * @return the value of the given local variable. + * @throws IndexOutOfBoundsException if the variable does not exist. + */ + public V getLocal(final int index) { + if (index >= nLocals) { + throw new IndexOutOfBoundsException("Trying to access an inexistant local variable"); + } + return values[index]; + } + + /** + * Sets the value of the given local variable. + * + * @param index a local variable index. + * @param value the new value of this local variable. + * @throws IndexOutOfBoundsException if the variable does not exist. + */ + public void setLocal(final int index, final V value) { + if (index >= nLocals) { + throw new IndexOutOfBoundsException("Trying to access an inexistant local variable " + index); + } + values[index] = value; + } + + /** + * Returns the number of values in the operand stack of this frame. Long and double values are + * treated as single values. + * + * @return the number of values in the operand stack of this frame. + */ + public int getStackSize() { + return nStack; + } + + /** + * Returns the value of the given operand stack slot. + * + * @param index the index of an operand stack slot. + * @return the value of the given operand stack slot. + * @throws IndexOutOfBoundsException if the operand stack slot does not exist. + */ + public V getStack(final int index) { + return values[nLocals + index]; + } + + /** Clears the operand stack of this frame. */ + public void clearStack() { + nStack = 0; + } + + /** + * Pops a value from the operand stack of this frame. + * + * @return the value that has been popped from the stack. + * @throws IndexOutOfBoundsException if the operand stack is empty. + */ + public V pop() { + if (nStack == 0) { + throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack."); + } + return values[nLocals + (--nStack)]; + } + + /** + * Pushes a value into the operand stack of this frame. + * + * @param value the value that must be pushed into the stack. + * @throws IndexOutOfBoundsException if the operand stack is full. + */ + public void push(final V value) { + if (nLocals + nStack >= values.length) { + throw new IndexOutOfBoundsException("Insufficient maximum stack size."); + } + values[nLocals + (nStack++)] = value; + } + + /** + * Simulates the execution of the given instruction on this execution stack frame. + * + * @param insn the instruction to execute. + * @param interpreter the interpreter to use to compute values from other values. + * @throws AnalyzerException if the instruction cannot be executed on this execution frame (e.g. a + * POP on an empty operand stack). + */ + public void execute(final AbstractInsnNode insn, final Interpreter interpreter) + throws AnalyzerException { + V value1; + V value2; + V value3; + V value4; + int var; + + switch (insn.getOpcode()) { + case Opcodes.NOP: + break; + case Opcodes.ACONST_NULL: + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.LDC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.ILOAD: + case Opcodes.LLOAD: + case Opcodes.FLOAD: + case Opcodes.DLOAD: + case Opcodes.ALOAD: + push(interpreter.copyOperation(insn, getLocal(((VarInsnNode) insn).var))); + break; + case Opcodes.ISTORE: + case Opcodes.LSTORE: + case Opcodes.FSTORE: + case Opcodes.DSTORE: + case Opcodes.ASTORE: + value1 = interpreter.copyOperation(insn, pop()); + var = ((VarInsnNode) insn).var; + setLocal(var, value1); + if (value1.getSize() == 2) { + setLocal(var + 1, interpreter.newValue(null)); + } + if (var > 0) { + Value local = getLocal(var - 1); + if (local != null && local.getSize() == 2) { + setLocal(var - 1, interpreter.newValue(null)); + } + } + break; + case Opcodes.IASTORE: + case Opcodes.LASTORE: + case Opcodes.FASTORE: + case Opcodes.DASTORE: + case Opcodes.AASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + value3 = pop(); + value2 = pop(); + value1 = pop(); + interpreter.ternaryOperation(insn, value1, value2, value3); + break; + case Opcodes.POP: + if (pop().getSize() == 2) { + throw new AnalyzerException(insn, "Illegal use of POP"); + } + break; + case Opcodes.POP2: + if (pop().getSize() == 1 && pop().getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of POP2"); + } + break; + case Opcodes.DUP: + value1 = pop(); + if (value1.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP"); + } + push(value1); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.DUP_X1: + value1 = pop(); + value2 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP_X1"); + } + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + case Opcodes.DUP_X2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } else { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + } + } + throw new AnalyzerException(insn, "Illegal use of DUP_X2"); + case Opcodes.DUP2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + push(value2); + push(value1); + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; + } + } else { + push(value1); + push(interpreter.copyOperation(insn, value1)); + break; + } + throw new AnalyzerException(insn, "Illegal use of DUP2"); + case Opcodes.DUP2_X1: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } + } else { + value2 = pop(); + if (value2.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + } + } + throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); + case Opcodes.DUP2_X2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + value4 = pop(); + if (value4.getSize() == 1) { + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + push(value4); + push(value3); + push(value2); + push(value1); + break; + } + } else { + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } + } else { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; + } + } else { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + } + } + throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); + case Opcodes.SWAP: + value2 = pop(); + value1 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of SWAP"); + } + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.IALOAD: + case Opcodes.LALOAD: + case Opcodes.FALOAD: + case Opcodes.DALOAD: + case Opcodes.AALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + case Opcodes.IADD: + case Opcodes.LADD: + case Opcodes.FADD: + case Opcodes.DADD: + case Opcodes.ISUB: + case Opcodes.LSUB: + case Opcodes.FSUB: + case Opcodes.DSUB: + case Opcodes.IMUL: + case Opcodes.LMUL: + case Opcodes.FMUL: + case Opcodes.DMUL: + case Opcodes.IDIV: + case Opcodes.LDIV: + case Opcodes.FDIV: + case Opcodes.DDIV: + case Opcodes.IREM: + case Opcodes.LREM: + case Opcodes.FREM: + case Opcodes.DREM: + case Opcodes.ISHL: + case Opcodes.LSHL: + case Opcodes.ISHR: + case Opcodes.LSHR: + case Opcodes.IUSHR: + case Opcodes.LUSHR: + case Opcodes.IAND: + case Opcodes.LAND: + case Opcodes.IOR: + case Opcodes.LOR: + case Opcodes.IXOR: + case Opcodes.LXOR: + case Opcodes.LCMP: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.IINC: + var = ((IincInsnNode) insn).var; + setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); + break; + case Opcodes.I2L: + case Opcodes.I2F: + case Opcodes.I2D: + case Opcodes.L2I: + case Opcodes.L2F: + case Opcodes.L2D: + case Opcodes.F2I: + case Opcodes.F2L: + case Opcodes.F2D: + case Opcodes.D2I: + case Opcodes.D2L: + case Opcodes.D2F: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + case Opcodes.PUTFIELD: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.GOTO: + break; + case Opcodes.JSR: + push(interpreter.newOperation(insn)); + break; + case Opcodes.RET: + break; + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IRETURN: + case Opcodes.LRETURN: + case Opcodes.FRETURN: + case Opcodes.DRETURN: + case Opcodes.ARETURN: + value1 = pop(); + interpreter.unaryOperation(insn, value1); + interpreter.returnOperation(insn, value1, returnValue); + break; + case Opcodes.RETURN: + if (returnValue != null) { + throw new AnalyzerException(insn, "Incompatible return type"); + } + break; + case Opcodes.GETSTATIC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.PUTSTATIC: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.GETFIELD: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: + { + List valueList = new ArrayList(); + String methodDescriptor = ((MethodInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(methodDescriptor).length; i > 0; --i) { + valueList.add(0, pop()); + } + if (insn.getOpcode() != Opcodes.INVOKESTATIC) { + valueList.add(0, pop()); + } + if (Type.getReturnType(methodDescriptor) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, valueList); + } else { + push(interpreter.naryOperation(insn, valueList)); + } + break; + } + case Opcodes.INVOKEDYNAMIC: + { + List valueList = new ArrayList(); + String methodDesccriptor = ((InvokeDynamicInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(methodDesccriptor).length; i > 0; --i) { + valueList.add(0, pop()); + } + if (Type.getReturnType(methodDesccriptor) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, valueList); + } else { + push(interpreter.naryOperation(insn, valueList)); + } + break; + } + case Opcodes.NEW: + push(interpreter.newOperation(insn)); + break; + case Opcodes.NEWARRAY: + case Opcodes.ANEWARRAY: + case Opcodes.ARRAYLENGTH: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ATHROW: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.CHECKCAST: + case Opcodes.INSTANCEOF: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.MULTIANEWARRAY: + List valueList = new ArrayList(); + for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { + valueList.add(0, pop()); + } + push(interpreter.naryOperation(insn, valueList)); + break; + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + interpreter.unaryOperation(insn, pop()); + break; + default: + throw new AnalyzerException(insn, "Illegal opcode " + insn.getOpcode()); + } + } + + /** + * Merges the given frame into this frame. + * + * @param frame a frame. This frame is left unchanged by this method. + * @param interpreter the interpreter used to merge values. + * @return true if this frame has been changed as a result of the merge operation, or + * false otherwise. + * @throws AnalyzerException if the frames have incompatible sizes. + */ + public boolean merge(final Frame frame, final Interpreter interpreter) + throws AnalyzerException { + if (nStack != frame.nStack) { + throw new AnalyzerException(null, "Incompatible stack heights"); + } + boolean changed = false; + for (int i = 0; i < nLocals + nStack; ++i) { + V v = interpreter.merge(values[i], frame.values[i]); + if (!v.equals(values[i])) { + values[i] = v; + changed = true; + } + } + return changed; + } + + /** + * Merges the given frame into this frame (case of a subroutine). The operand stacks are not + * merged, and only the local variables that have not been used by the subroutine are merged. + * + * @param frame a frame. This frame is left unchanged by this method. + * @param localsUsed the local variables that are read or written by the subroutine. The i-th + * element is true if and only if the local variable at index i is read or written by the + * subroutine. + * @return true if this frame has been changed as a result of the merge operation, or + * false otherwise. + */ + public boolean merge(final Frame frame, final boolean[] localsUsed) { + boolean changed = false; + for (int i = 0; i < nLocals; ++i) { + if (!localsUsed[i] && !values[i].equals(frame.values[i])) { + values[i] = frame.values[i]; + changed = true; + } + } + return changed; + } + + /** + * Returns a string representation of this frame. + * + * @return a string representation of this frame. + */ + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < getLocals(); ++i) { + stringBuilder.append(getLocal(i)); + } + stringBuilder.append(' '); + for (int i = 0; i < getStackSize(); ++i) { + stringBuilder.append(getStack(i).toString()); + } + return stringBuilder.toString(); + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Interpreter.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Interpreter.java new file mode 100644 index 000000000..c0a7cbdd8 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Interpreter.java @@ -0,0 +1,198 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.List; + +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; + +/** + * A semantic bytecode interpreter. More precisely, this interpreter only manages the computation of + * values from other values: it does not manage the transfer of values to or from the stack, and to + * or from the local variables. This separation allows a generic bytecode {@link Analyzer} to work + * with various semantic interpreters, without needing to duplicate the code to simulate the + * transfer of values. + * + * @param type of the Value used for the analysis. + * @author Eric Bruneton + */ +public abstract class Interpreter { + + /** + * The ASM API version supported by this interpreter. The value of this field must be one of + * {@link org.objectweb.asm.Opcodes#ASM4}, {@link org.objectweb.asm.Opcodes#ASM5}, {@link + * org.objectweb.asm.Opcodes#ASM6} or {@link org.objectweb.asm.Opcodes#ASM7_EXPERIMENTAL}. + */ + protected final int api; + + /** + * Constructs a new {@link Interpreter}. + * + * @param api the ASM API version supported by this interpreter. Must be one of {@link + * org.objectweb.asm.Opcodes#ASM4}, {@link org.objectweb.asm.Opcodes#ASM5}, {@link + * org.objectweb.asm.Opcodes#ASM6} or {@link org.objectweb.asm.Opcodes#ASM7_EXPERIMENTAL}. + */ + protected Interpreter(final int api) { + this.api = api; + } + + /** + * Creates a new value that represents the given type. + * + *

Called for method parameters (including this), exception handler variable and + * with null type for variables reserved by long and double types. + * + * @param type a primitive or reference type, or null to represent an uninitialized + * value. + * @return a value that represents the given type. The size of the returned value must be equal to + * the size of the given type. + */ + public abstract V newValue(Type type); + + /** + * Interprets a bytecode instruction without arguments. This method is called for the following + * opcodes: + * + *

ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5, + * LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, BIPUSH, SIPUSH, LDC, JSR, + * GETSTATIC, NEW + * + * @param insn the bytecode instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract V newOperation(AbstractInsnNode insn) throws AnalyzerException; + + /** + * Interprets a bytecode instruction that moves a value on the stack or to or from local + * variables. This method is called for the following opcodes: + * + *

ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE, DUP, DUP_X1, + * DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP + * + * @param insn the bytecode instruction to be interpreted. + * @param value the value that must be moved by the instruction. + * @return the result of the interpretation of the given instruction. The returned value must be + * equal to the given value. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract V copyOperation(AbstractInsnNode insn, V value) throws AnalyzerException; + + /** + * Interprets a bytecode instruction with a single argument. This method is called for the + * following opcodes: + * + *

INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, + * I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, + * FRETURN, DRETURN, ARETURN, PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, + * CHECKCAST, INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL + * + * @param insn the bytecode instruction to be interpreted. + * @param value the argument of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract V unaryOperation(AbstractInsnNode insn, V value) throws AnalyzerException; + + /** + * Interprets a bytecode instruction with two arguments. This method is called for the following + * opcodes: + * + *

IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD, LADD, FADD, DADD, + * ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, + * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, + * DCMPL, DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, + * IF_ACMPNE, PUTFIELD + * + * @param insn the bytecode instruction to be interpreted. + * @param value1 the first argument of the instruction to be interpreted. + * @param value2 the second argument of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2) + throws AnalyzerException; + + /** + * Interprets a bytecode instruction with three arguments. This method is called for the following + * opcodes: + * + *

IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE + * + * @param insn the bytecode instruction to be interpreted. + * @param value1 the first argument of the instruction to be interpreted. + * @param value2 the second argument of the instruction to be interpreted. + * @param value3 the third argument of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract V ternaryOperation(AbstractInsnNode insn, V value1, V value2, V value3) + throws AnalyzerException; + + /** + * Interprets a bytecode instruction with a variable number of arguments. This method is called + * for the following opcodes: + * + *

INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE, MULTIANEWARRAY and + * INVOKEDYNAMIC + * + * @param insn the bytecode instruction to be interpreted. + * @param values the arguments of the instruction to be interpreted. + * @return the result of the interpretation of the given instruction. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract V naryOperation(AbstractInsnNode insn, List values) + throws AnalyzerException; + + /** + * Interprets a bytecode return instruction. This method is called for the following opcodes: + * + *

IRETURN, LRETURN, FRETURN, DRETURN, ARETURN + * + * @param insn the bytecode instruction to be interpreted. + * @param value the argument of the instruction to be interpreted. + * @param expected the expected return type of the analyzed method. + * @throws AnalyzerException if an error occured during the interpretation. + */ + public abstract void returnOperation(AbstractInsnNode insn, V value, V expected) + throws AnalyzerException; + + /** + * Merges two values. The merge operation must return a value that represents both values (for + * instance, if the two values are two types, the merged value must be a common super type of the + * two types. If the two values are integer intervals, the merged value must be an interval that + * contains the previous ones. Likewise for other types of values). + * + * @param value1 a value. + * @param value2 another value. + * @return the merged value. If the merged value is equal to value1, this method + * must return value1. + */ + public abstract V merge(V value1, V value2); +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java new file mode 100644 index 000000000..3df6b5097 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SimpleVerifier.java @@ -0,0 +1,372 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.List; + +import org.objectweb.asm.Type; + +/** + * An extended {@link BasicVerifier} that performs more precise verifications. This verifier + * computes exact class types, instead of using a single "object reference" type (as done in {@link + * BasicVerifier}). + * + * @author Eric Bruneton + * @author Bing Ran + */ +public class SimpleVerifier extends BasicVerifier { + + /** The type of the class that is verified. */ + private final Type currentClass; + + /** The type of the super class of the class that is verified. */ + private final Type currentSuperClass; + + /** The types of the interfaces directly implemented by the class that is verified. */ + private final List currentClassInterfaces; + + /** Whether the class that is verified is an interface. */ + private final boolean isInterface; + + /** The loader to use to load the referenced classes. */ + private ClassLoader loader = getClass().getClassLoader(); + + /** + * Constructs a new {@link SimpleVerifier}. Subclasses must not use this constructor. + * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version. + */ + public SimpleVerifier() { + this(null, null, false); + } + + /** + * Constructs a new {@link SimpleVerifier} to verify a specific class. This class will not be + * loaded into the JVM since it may be incorrect. Subclasses must not use this constructor. + * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version. + * + * @param currentClass the type of the class to be verified. + * @param currentSuperClass the type of the super class of the class to be verified. + * @param isInterface whether the class to be verifier is an interface. + */ + public SimpleVerifier( + final Type currentClass, final Type currentSuperClass, final boolean isInterface) { + this(currentClass, currentSuperClass, null, isInterface); + } + + /** + * Constructs a new {@link SimpleVerifier} to verify a specific class. This class will not be + * loaded into the JVM since it may be incorrect. Subclasses must not use this constructor. + * Instead, they must use the {@link #SimpleVerifier(int, Type, Type, List, boolean)} version. + * + * @param currentClass the type of the class to be verified. + * @param currentSuperClass the type of the super class of the class to be verified. + * @param currentClassInterfaces the types of the interfaces directly implemented by the class to + * be verified. + * @param isInterface whether the class to be verifier is an interface. + */ + public SimpleVerifier( + final Type currentClass, + final Type currentSuperClass, + final List currentClassInterfaces, + final boolean isInterface) { + this(ASM6, currentClass, currentSuperClass, currentClassInterfaces, isInterface); + if (getClass() != SimpleVerifier.class) { + throw new IllegalStateException(); + } + } + + /** + * Constructs a new {@link SimpleVerifier} to verify a specific class. This class will not be + * loaded into the JVM since it may be incorrect. + * + * @param api the ASM API version supported by this verifier. Must be one of {@link + * org.objectweb.asm.Opcodes#ASM4}, {@link org.objectweb.asm.Opcodes#ASM5}, {@link + * org.objectweb.asm.Opcodes#ASM6} or {@link org.objectweb.asm.Opcodes#ASM7_EXPERIMENTAL}. + * @param currentClass the type of the class to be verified. + * @param currentSuperClass the type of the super class of the class to be verified. + * @param currentClassInterfaces the types of the interfaces directly implemented by the class to + * be verified. + * @param isInterface whether the class to be verifier is an interface. + */ + protected SimpleVerifier( + final int api, + final Type currentClass, + final Type currentSuperClass, + final List currentClassInterfaces, + final boolean isInterface) { + super(api); + this.currentClass = currentClass; + this.currentSuperClass = currentSuperClass; + this.currentClassInterfaces = currentClassInterfaces; + this.isInterface = isInterface; + } + + /** + * Sets the ClassLoader to be used in {@link #getClass}. + * + * @param loader the ClassLoader to use. + */ + public void setClassLoader(final ClassLoader loader) { + this.loader = loader; + } + + @Override + public BasicValue newValue(final Type type) { + if (type == null) { + return BasicValue.UNINITIALIZED_VALUE; + } + + boolean isArray = type.getSort() == Type.ARRAY; + if (isArray) { + switch (type.getElementType().getSort()) { + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + return new BasicValue(type); + default: + break; + } + } + + BasicValue value = super.newValue(type); + if (BasicValue.REFERENCE_VALUE.equals(value)) { + if (isArray) { + value = newValue(type.getElementType()); + StringBuilder descriptor = new StringBuilder(); + for (int i = 0; i < type.getDimensions(); ++i) { + descriptor.append('['); + } + descriptor.append(value.getType().getDescriptor()); + value = new BasicValue(Type.getType(descriptor.toString())); + } else { + value = new BasicValue(type); + } + } + return value; + } + + @Override + protected boolean isArrayValue(final BasicValue value) { + Type type = value.getType(); + return type != null && (type.getSort() == Type.ARRAY || type.equals(NULL_TYPE)); + } + + @Override + protected BasicValue getElementValue(final BasicValue objectArrayValue) throws AnalyzerException { + Type arrayType = objectArrayValue.getType(); + if (arrayType != null) { + if (arrayType.getSort() == Type.ARRAY) { + return newValue(Type.getType(arrayType.getDescriptor().substring(1))); + } else if (arrayType.equals(NULL_TYPE)) { + return objectArrayValue; + } + } + throw new AssertionError(); + } + + @Override + protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) { + Type expectedType = expected.getType(); + Type type = value.getType(); + switch (expectedType.getSort()) { + case Type.INT: + case Type.FLOAT: + case Type.LONG: + case Type.DOUBLE: + return type.equals(expectedType); + case Type.ARRAY: + case Type.OBJECT: + if (type.equals(NULL_TYPE)) { + return true; + } else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { + return isAssignableFrom(expectedType, type); + } else { + return false; + } + default: + throw new AssertionError(); + } + } + + @Override + public BasicValue merge(final BasicValue value1, final BasicValue value2) { + if (!value1.equals(value2)) { + Type type1 = value1.getType(); + Type type2 = value2.getType(); + if (type1 != null + && (type1.getSort() == Type.OBJECT || type1.getSort() == Type.ARRAY) + && type2 != null + && (type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY)) { + if (type1.equals(NULL_TYPE)) { + return value2; + } + if (type2.equals(NULL_TYPE)) { + return value1; + } + if (isAssignableFrom(type1, type2)) { + return value1; + } + if (isAssignableFrom(type2, type1)) { + return value2; + } + int numDimensions = 0; + if (type1.getSort() == Type.ARRAY + && type2.getSort() == Type.ARRAY + && type1.getDimensions() == type2.getDimensions() + && type1.getElementType().getSort() == Type.OBJECT + && type2.getElementType().getSort() == Type.OBJECT) { + numDimensions = type1.getDimensions(); + type1 = type1.getElementType(); + type2 = type2.getElementType(); + } + do { + if (type1 == null || isInterface(type1)) { + return newValue(Type.getObjectType("java/lang/Object"), numDimensions); + } + type1 = getSuperClass(type1); + if (isAssignableFrom(type1, type2)) { + return newValue(type1, numDimensions); + } + } while (true); + } + return BasicValue.UNINITIALIZED_VALUE; + } + return value1; + } + + private BasicValue newValue(final Type type, final int dimensions) { + if (dimensions == 0) { + return newValue(type); + } else { + StringBuilder descriptor = new StringBuilder(); + for (int i = 0; i < dimensions; ++i) { + descriptor.append('['); + } + descriptor.append(type.getDescriptor()); + return newValue(Type.getType(descriptor.toString())); + } + } + + /** + * Returns whether the given type corresponds to the type of an interface. The default + * implementation of this method loads the class and uses the reflection API to return its result + * (unless the given type corresponds to the class being verified). + * + * @param type a type. + * @return whether 'type' corresponds to an interface. + */ + protected boolean isInterface(final Type type) { + if (currentClass != null && type.equals(currentClass)) { + return isInterface; + } + return getClass(type).isInterface(); + } + + /** + * Returns the type corresponding to the super class of the given type. The default implementation + * of this method loads the class and uses the reflection API to return its result (unless the + * given type corresponds to the class being verified). + * + * @param type a type. + * @return the type corresponding to the super class of 'type'. + */ + protected Type getSuperClass(final Type type) { + if (currentClass != null && type.equals(currentClass)) { + return currentSuperClass; + } + Class superClass = getClass(type).getSuperclass(); + return superClass == null ? null : Type.getType(superClass); + } + + /** + * Returns whether the class corresponding to the first argument is either the same as, or is a + * superclass or superinterface of the class corresponding to the second argument. The default + * implementation of this method loads the classes and uses the reflection API to return its + * result (unless the result can be computed from the class being verified, and the types of its + * super classes and implemented interfaces). + * + * @param type1 a type. + * @param type2 another type. + * @return whether the class corresponding to 'type1' is either the same as, or is a superclass or + * superinterface of the class corresponding to 'type2'. + */ + protected boolean isAssignableFrom(final Type type1, final Type type2) { + if (type1.equals(type2)) { + return true; + } + if (currentClass != null && type1.equals(currentClass)) { + if (getSuperClass(type2) == null) { + return false; + } else { + if (isInterface) { + return type2.getSort() == Type.OBJECT || type2.getSort() == Type.ARRAY; + } + return isAssignableFrom(type1, getSuperClass(type2)); + } + } + if (currentClass != null && type2.equals(currentClass)) { + if (isAssignableFrom(type1, currentSuperClass)) { + return true; + } + if (currentClassInterfaces != null) { + for (int i = 0; i < currentClassInterfaces.size(); ++i) { + Type currentClassInterface = currentClassInterfaces.get(i); + if (isAssignableFrom(type1, currentClassInterface)) { + return true; + } + } + } + return false; + } + Class class1 = getClass(type1); + if (class1.isInterface()) { + class1 = Object.class; + } + return class1.isAssignableFrom(getClass(type2)); + } + + /** + * Loads the class corresponding to the given type. The class is loaded with the class loader + * specified with {@link #setClassLoader}, or with the class loader of this class if no class + * loader was specified. + * + * @param type a type. + * @return the class corresponding to 'type'. + */ + protected Class getClass(final Type type) { + try { + if (type.getSort() == Type.ARRAY) { + return Class.forName(type.getDescriptor().replace('/', '.'), false, loader); + } + return Class.forName(type.getClassName(), false, loader); + } catch (ClassNotFoundException e) { + throw new TypeNotPresentException(e.toString(), e); + } + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SmallSet.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SmallSet.java new file mode 100644 index 000000000..3ca92e7ee --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SmallSet.java @@ -0,0 +1,190 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.AbstractSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * An immutable set of at most two elements, optimized for speed compared to a generic set + * implementation. + * + * @author Eric Bruneton + */ +final class SmallSet extends AbstractSet { + + /** The first element of this set, maybe null. */ + private final T element1; + + /** + * The second element of this set, maybe null. If {@link #element1} is null then + * this field must be null, otherwise it must be different from {@link #element1}. + */ + private final T element2; + + // ----------------------------------------------------------------------------------------------- + // Constructors + // ----------------------------------------------------------------------------------------------- + + /** Constructs an empty set. */ + SmallSet() { + this.element1 = null; + this.element2 = null; + } + + /** + * Constructs a set with exactly one element. + * + * @param element the unique set element. + */ + SmallSet(final T element) { + this.element1 = element; + this.element2 = null; + } + + /** + * Constructs a new {@link SmallSet}. + * + * @param element1 see {@link #element1}. + * @param element2 see {@link #element2}. + */ + private SmallSet(final T element1, final T element2) { + this.element1 = element1; + this.element2 = element2; + } + + // ----------------------------------------------------------------------------------------------- + // Implementation of the inherited abstract methods + // ----------------------------------------------------------------------------------------------- + + @Override + public Iterator iterator() { + return new IteratorImpl(element1, element2); + } + + static class IteratorImpl implements Iterator { + + /** The next element to return in {@link #next}. Maybe null. */ + private T firstElement; + + /** + * The element to return in {@link #next}, after {@link #firstElement} is returned. If {@link + * #firstElement} is null then this field must be null, otherwise it must be + * different from {@link #firstElement}. + */ + private T secondElement; + + IteratorImpl(final T firstElement, final T secondElement) { + this.firstElement = firstElement; + this.secondElement = secondElement; + } + + public boolean hasNext() { + return firstElement != null; + } + + public T next() { + if (firstElement == null) { + throw new NoSuchElementException(); + } + T element = firstElement; + firstElement = secondElement; + secondElement = null; + return element; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } + + @Override + public int size() { + return element1 == null ? 0 : (element2 == null ? 1 : 2); + } + + // ----------------------------------------------------------------------------------------------- + // Utility methods + // ----------------------------------------------------------------------------------------------- + + /** + * Returns the union of this set and of the given set. + * + * @param otherSet another small set. + * @return the union of this set and of otherSet. + */ + Set union(final SmallSet otherSet) { + // If the two sets are equal, return this set. + if ((otherSet.element1 == element1 && otherSet.element2 == element2) + || (otherSet.element1 == element2 && otherSet.element2 == element1)) { + return this; + } + // If one set is empty, return the other. + if (otherSet.element1 == null) { + return this; + } + if (element1 == null) { + return otherSet; + } + + // At this point we know that the two sets are non empty and are different. + // If otherSet contains exactly one element: + if (otherSet.element2 == null) { + // If this set also contains exactly one element, we have two distinct elements. + if (element2 == null) { + return new SmallSet(element1, otherSet.element1); + } + // If otherSet is included in this set, return this set. + if (otherSet.element1 == element1 || otherSet.element1 == element2) { + return this; + } + } + // If this set contains exactly one element, then otherSet contains two elements (because of the + // above tests). Thus, if otherSet contains this set, return otherSet: + if (element2 == null && (element1 == otherSet.element1 || element1 == otherSet.element2)) { + return otherSet; + } + + // At this point we know that there are at least 3 distinct elements, so we need a generic set + // to store the result. + HashSet result = new HashSet(4); + result.add(element1); + if (element2 != null) { + result.add(element2); + } + result.add(otherSet.element1); + if (otherSet.element2 != null) { + result.add(otherSet.element2); + } + return result; + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SourceInterpreter.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SourceInterpreter.java new file mode 100644 index 000000000..ce89e77f9 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SourceInterpreter.java @@ -0,0 +1,212 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.InvokeDynamicInsnNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; + +/** + * An {@link Interpreter} for {@link SourceValue} values. + * + * @author Eric Bruneton + */ +public class SourceInterpreter extends Interpreter implements Opcodes { + + /** + * Constructs a new {@link SourceInterpreter} for the latest ASM API version. Subclasses must + * not use this constructor. Instead, they must use the {@link #SourceInterpreter(int)} + * version. + */ + public SourceInterpreter() { + super(ASM6); + if (getClass() != SourceInterpreter.class) { + throw new IllegalStateException(); + } + } + + /** + * Constructs a new {@link SourceInterpreter}. + * + * @param api the ASM API version supported by this interpreter. Must be one of {@link + * org.objectweb.asm.Opcodes#ASM4}, {@link org.objectweb.asm.Opcodes#ASM5}, {@link + * org.objectweb.asm.Opcodes#ASM6} or {@link org.objectweb.asm.Opcodes#ASM7_EXPERIMENTAL}. + */ + protected SourceInterpreter(final int api) { + super(api); + } + + @Override + public SourceValue newValue(final Type type) { + if (type == Type.VOID_TYPE) { + return null; + } + return new SourceValue(type == null ? 1 : type.getSize()); + } + + @Override + public SourceValue newOperation(final AbstractInsnNode insn) { + int size; + switch (insn.getOpcode()) { + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + size = 2; + break; + case LDC: + Object value = ((LdcInsnNode) insn).cst; + size = value instanceof Long || value instanceof Double ? 2 : 1; + break; + case GETSTATIC: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; + } + return new SourceValue(size, insn); + } + + @Override + public SourceValue copyOperation(final AbstractInsnNode insn, final SourceValue value) { + return new SourceValue(value.getSize(), insn); + } + + @Override + public SourceValue unaryOperation(final AbstractInsnNode insn, final SourceValue value) { + int size; + switch (insn.getOpcode()) { + case LNEG: + case DNEG: + case I2L: + case I2D: + case L2D: + case F2L: + case F2D: + case D2L: + size = 2; + break; + case GETFIELD: + size = Type.getType(((FieldInsnNode) insn).desc).getSize(); + break; + default: + size = 1; + } + return new SourceValue(size, insn); + } + + @Override + public SourceValue binaryOperation( + final AbstractInsnNode insn, final SourceValue value1, final SourceValue value2) { + int size; + switch (insn.getOpcode()) { + case LALOAD: + case DALOAD: + case LADD: + case DADD: + case LSUB: + case DSUB: + case LMUL: + case DMUL: + case LDIV: + case DDIV: + case LREM: + case DREM: + case LSHL: + case LSHR: + case LUSHR: + case LAND: + case LOR: + case LXOR: + size = 2; + break; + default: + size = 1; + } + return new SourceValue(size, insn); + } + + @Override + public SourceValue ternaryOperation( + final AbstractInsnNode insn, + final SourceValue value1, + final SourceValue value2, + final SourceValue value3) { + return new SourceValue(1, insn); + } + + @Override + public SourceValue naryOperation( + final AbstractInsnNode insn, final List values) { + int size; + int opcode = insn.getOpcode(); + if (opcode == MULTIANEWARRAY) { + size = 1; + } else if (opcode == INVOKEDYNAMIC) { + size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize(); + } else { + size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize(); + } + return new SourceValue(size, insn); + } + + @Override + public void returnOperation( + final AbstractInsnNode insn, final SourceValue value, final SourceValue expected) { + // Nothing to do. + } + + @Override + public SourceValue merge(final SourceValue value1, final SourceValue value2) { + if (value1.insns instanceof SmallSet && value2.insns instanceof SmallSet) { + Set setUnion = + ((SmallSet) value1.insns) + .union((SmallSet) value2.insns); + if (setUnion == value1.insns && value1.size == value2.size) { + return value1; + } else { + return new SourceValue(Math.min(value1.size, value2.size), setUnion); + } + } + if (value1.size != value2.size || !value1.insns.containsAll(value2.insns)) { + HashSet setUnion = new HashSet(); + setUnion.addAll(value1.insns); + setUnion.addAll(value2.insns); + return new SourceValue(Math.min(value1.size, value2.size), setUnion); + } + return value1; + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SourceValue.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SourceValue.java new file mode 100644 index 000000000..86e8c7fed --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/SourceValue.java @@ -0,0 +1,119 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.Set; + +import org.objectweb.asm.tree.AbstractInsnNode; + +/** + * A {@link Value} which keeps track of the bytecode instructions that can produce it. + * + * @author Eric Bruneton + */ +public class SourceValue implements Value { + + /** + * The size of this value, in 32 bits words. This size is 1 for byte, boolean, char, short, int, + * float, object and array types, and 2 for long and double. + */ + public final int size; + + /** + * The instructions that can produce this value. For example, for the Java code below, the + * instructions that can produce the value of i at line 5 are the two ISTORE instructions + * at line 1 and 3: + * + *

+   * 1: i = 0;
+   * 2: if (...) {
+   * 3:   i = 1;
+   * 4: }
+   * 5: return i;
+   * 
+ */ + public final Set insns; + + /** + * Constructs a new {@link SourceValue}. + * + * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char, + * short, int, float, object and array types, and 2 for long and double. + */ + public SourceValue(final int size) { + this(size, new SmallSet()); + } + + /** + * Constructs a new {@link SourceValue}. + * + * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char, + * short, int, float, object and array types, and 2 for long and double. + * @param insnNode an instruction that can produce this value. + */ + public SourceValue(final int size, final AbstractInsnNode insnNode) { + this.size = size; + this.insns = new SmallSet(insnNode); + } + + /** + * Constructs a new {@link SourceValue}. + * + * @param size the size of this value, in 32 bits words. This size is 1 for byte, boolean, char, + * short, int, float, object and array types, and 2 for long and double. + * @param insnSet the instructions that can produce this value. + */ + public SourceValue(final int size, final Set insnSet) { + this.size = size; + this.insns = insnSet; + } + + /** + * Returns the size of this value. + * + * @return the size of this value, in 32 bits words. This size is 1 for byte, boolean, char, + * short, int, float, object and array types, and 2 for long and double. + */ + public int getSize() { + return size; + } + + @Override + public boolean equals(final Object value) { + if (!(value instanceof SourceValue)) { + return false; + } + SourceValue sourceValue = (SourceValue) value; + return size == sourceValue.size && insns.equals(sourceValue.insns); + } + + @Override + public int hashCode() { + return insns.hashCode(); + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Subroutine.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Subroutine.java new file mode 100644 index 000000000..6e675ad64 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Subroutine.java @@ -0,0 +1,108 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import java.util.ArrayList; +import java.util.List; + +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; + +/** + * A method subroutine (corresponds to a JSR instruction). + * + * @author Eric Bruneton + */ +final class Subroutine { + + /** The start of this subroutine. */ + final LabelNode start; + + /** + * The local variables that are read or written by this subroutine. The i-th element is true if + * and only if the local variable at index i is read or written by this subroutine. + */ + final boolean[] localsUsed; + + /** The JSR instructions that jump to this subroutine. */ + final List callers; + + /** + * Constructs a new {@link Subroutine}. + * + * @param start the start of this subroutine. + * @param maxLocals the local variables that are read or written by this subroutine. + * @param caller a JSR instruction that jump to this subroutine. + */ + Subroutine(final LabelNode start, final int maxLocals, final JumpInsnNode caller) { + this.start = start; + this.localsUsed = new boolean[maxLocals]; + this.callers = new ArrayList(); + callers.add(caller); + } + + /** + * Constructs a copy of the given {@link Subroutine}. + * + * @param subroutine the subroutine to copy. + */ + Subroutine(final Subroutine subroutine) { + this.start = subroutine.start; + this.localsUsed = new boolean[subroutine.localsUsed.length]; + this.callers = new ArrayList(subroutine.callers); + System.arraycopy(subroutine.localsUsed, 0, this.localsUsed, 0, subroutine.localsUsed.length); + } + + /** + * Merges the given subroutine into this subroutine. The local variables read or written by the + * given subroutine are marked as read or written by this one, and the callers of the given + * subroutine are added as callers of this one (if both have the same start). + * + * @param subroutine another subroutine. This subroutine is left unchanged by this method. + * @return whether this subroutine has been modified by this method. + */ + public boolean merge(final Subroutine subroutine) { + boolean changed = false; + for (int i = 0; i < localsUsed.length; ++i) { + if (subroutine.localsUsed[i] && !localsUsed[i]) { + localsUsed[i] = true; + changed = true; + } + } + if (subroutine.start == start) { + for (int i = 0; i < subroutine.callers.size(); ++i) { + JumpInsnNode caller = subroutine.callers.get(i); + if (!callers.contains(caller)) { + callers.add(caller); + changed = true; + } + } + } + return changed; + } +} diff --git a/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Value.java b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Value.java new file mode 100644 index 000000000..669f075f0 --- /dev/null +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/Value.java @@ -0,0 +1,44 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +/** + * An immutable symbolic value for the semantic interpretation of bytecode. + * + * @author Eric Bruneton + */ +public interface Value { + + /** + * Returns the size of this value in 32 bits words. This size should be 1 for byte, boolean, char, + * short, int, float, object and array types, and 2 for long and double. + * + * @return either 1 or 2. + */ + int getSize(); +} diff --git a/src/org/objectweb/asm/tree/analysis/package.html b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/package.html similarity index 71% rename from src/org/objectweb/asm/tree/analysis/package.html rename to asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/package.html index 228da0234..b60c7dd4f 100644 --- a/src/org/objectweb/asm/tree/analysis/package.html +++ b/asm-analysis/src/main/java/org/objectweb/asm/tree/analysis/package.html @@ -39,23 +39,21 @@

-ClassReader cr = new ClassReader(bytecode);
-ClassNode cn = new ClassNode();
-cr.accept(cn, ClassReader.SKIP_DEBUG);
+ClassReader classReader = new ClassReader(bytecode);
+ClassNode classNode = new ClassNode();
+classReader.accept(classNode, ClassReader.SKIP_DEBUG);
 
-List methods = cn.methods;
-for (int i = 0; i < methods.size(); ++i) {
-    MethodNode method = (MethodNode) methods.get(i);
-    if (method.instructions.size() > 0) {
-        Analyzer a = new Analyzer(new BasicInterpreter());
-        a.analyze(cn.name, method);
-        Frame[] frames = a.getFrames();
-        // Elements of the frames arrray now contains info for each instruction
-        // from the analyzed method. BasicInterpreter creates BasicValue, that
-        // is using simplified type system that distinguishes the UNINITIALZED,
-        // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
-        ...
-    }
+for (MethodNode method : classNode.methods) {
+  if (method.instructions.size() > 0) {
+    Analyzer analyzer = new Analyzer(new BasicInterpreter());
+    analyzer.analyze(classNode.name, method);
+    Frame[] frames = analyzer.getFrames();
+    // Elements of the frames array now contains info for each instruction
+    // from the analyzed method. BasicInterpreter creates BasicValue, that
+    // is using simplified type system that distinguishes the UNINITIALZED,
+    // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+    ...
+  }
 }
 
diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/AnalyzerTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/AnalyzerTest.java new file mode 100644 index 000000000..4cbb8c4e8 --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/AnalyzerTest.java @@ -0,0 +1,946 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.MethodNode; + +/** + * Analyzer tests. + * + * @author Eric Bruneton + */ +public class AnalyzerTest { + + protected ClassWriter classWriter; + + protected MethodVisitor methodVisitor; + + private Label startLabel; + + @BeforeEach + public void setUp() throws Exception { + classWriter = new ClassWriter(0); + classWriter.visit(Opcodes.V1_1, Opcodes.ACC_PUBLIC, "C", null, "java/lang/Object", null); + methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + methodVisitor.visitCode(); + methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); + methodVisitor.visitMethodInsn( + Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V", false); + methodVisitor.visitInsn(Opcodes.RETURN); + methodVisitor.visitMaxs(1, 1); + methodVisitor.visitEnd(); + methodVisitor = classWriter.visitMethod(Opcodes.ACC_PUBLIC, "m", "()V", null, null); + methodVisitor.visitCode(); + startLabel = new Label(); + LABEL(startLabel); + } + + private void NOP() { + methodVisitor.visitInsn(Opcodes.NOP); + } + + private void PUSH() { + methodVisitor.visitInsn(Opcodes.ICONST_0); + } + + private void POP() { + methodVisitor.visitInsn(Opcodes.POP); + } + + private void ICONST_0() { + methodVisitor.visitInsn(Opcodes.ICONST_0); + } + + private void ISTORE(final int var) { + methodVisitor.visitVarInsn(Opcodes.ISTORE, var); + } + + private void ALOAD(final int var) { + methodVisitor.visitVarInsn(Opcodes.ALOAD, var); + } + + private void ILOAD(final int var) { + methodVisitor.visitVarInsn(Opcodes.ILOAD, var); + } + + private void ASTORE(final int var) { + methodVisitor.visitVarInsn(Opcodes.ASTORE, var); + } + + private void RET(final int var) { + methodVisitor.visitVarInsn(Opcodes.RET, var); + } + + private void ATHROW() { + methodVisitor.visitInsn(Opcodes.ATHROW); + } + + private void ACONST_NULL() { + methodVisitor.visitInsn(Opcodes.ACONST_NULL); + } + + private void RETURN() { + methodVisitor.visitInsn(Opcodes.RETURN); + } + + private void LABEL(final Label l) { + methodVisitor.visitLabel(l); + } + + private void IINC(final int var, final int amnt) { + methodVisitor.visitIincInsn(var, amnt); + } + + private void GOTO(final Label l) { + methodVisitor.visitJumpInsn(Opcodes.GOTO, l); + } + + private void JSR(final Label l) { + methodVisitor.visitJumpInsn(Opcodes.JSR, l); + } + + private void IFNONNULL(final Label l) { + methodVisitor.visitJumpInsn(Opcodes.IFNONNULL, l); + } + + private void IFNE(final Label l) { + methodVisitor.visitJumpInsn(Opcodes.IFNE, l); + } + + private void TRYCATCH(final Label start, final Label end, final Label handler) { + methodVisitor.visitTryCatchBlock(start, end, handler, null); + } + + protected static class TestClassLoader extends ClassLoader { + + public TestClassLoader() {} + + public Class defineClass(final String name, final byte[] b) { + return defineClass(name, b, 0, b.length); + } + } + + /** + * Tests a method which has the most basic try{}finally form imaginable: + * + *
+   * public void a() {
+   *     int a = 0;
+   *     try {
+   *         a++;
+   *     } finally {
+   *         a--;
+   *     }
+   * }
+   * 
+ */ + @Test + public void testBasic() { + Label L0 = new Label(); + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + Label L4 = new Label(); + + ICONST_0(); + ISTORE(1); + + /* L0: body of try block. */ + LABEL(L0); + IINC(1, 1); + GOTO(L1); + + /* L2: exception handler. */ + LABEL(L2); + ASTORE(3); + JSR(L3); + ALOAD(3); + ATHROW(); + + /* L3: subroutine. */ + LABEL(L3); + ASTORE(2); + IINC(1, -1); + PUSH(); + PUSH(); + RET(2); + + /* L1: non-exceptional exit from try block. */ + LABEL(L1); + JSR(L3); + PUSH(); + PUSH(); + LABEL(L4); + RETURN(); + + TRYCATCH(L0, L2, L2); + TRYCATCH(L1, L4, L2); + + assertMaxs(4, 4); + } + + /** + * Tests a method which has an if/else-if w/in the finally clause: + * + *
+   * public void a() {
+   *     int a = 0;
+   *     try {
+   *         a++;
+   *     } finally {
+   *         if (a == 0)
+   *             a += 2;
+   *         else
+   *             a += 3;
+   *     }
+   * }
+   * 
+ */ + @Test + public void testIfElseInFinally() { + Label L0 = new Label(); + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + Label L4 = new Label(); + Label L5 = new Label(); + Label L6 = new Label(); + + ICONST_0(); + ISTORE(1); + + /* L0: body of try block. */ + LABEL(L0); + IINC(1, 1); + GOTO(L1); + + /* L2: exception handler. */ + LABEL(L2); + ASTORE(3); + JSR(L3); + PUSH(); + PUSH(); + ALOAD(3); + ATHROW(); + + /* L3: subroutine. */ + LABEL(L3); + ASTORE(2); + PUSH(); + PUSH(); + ILOAD(1); + IFNE(L4); + IINC(1, 2); + GOTO(L5); + + LABEL(L4); + IINC(1, 3); + + LABEL(L5); + RET(2); + + /* L1: non-exceptional exit from try block. */ + LABEL(L1); + JSR(L3); + LABEL(L6); + RETURN(); + + TRYCATCH(L0, L2, L2); + TRYCATCH(L1, L6, L2); + + assertMaxs(5, 4); + } + + /** + * Tests a simple nested finally: + * + *
+   * public void a1() {
+   *     int a = 0;
+   *     try {
+   *         a += 1;
+   *     } finally {
+   *         try {
+   *             a += 2;
+   *         } finally {
+   *             a += 3;
+   *         }
+   *     }
+   * }
+   * 
+ */ + @Test + public void testSimpleNestedFinally() { + Label L0 = new Label(); + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + Label L4 = new Label(); + Label L5 = new Label(); + + ICONST_0(); + ISTORE(1); + + // L0: Body of try block. + LABEL(L0); + IINC(1, 1); + JSR(L3); + GOTO(L1); + + // L2: First exception handler. + LABEL(L2); + ASTORE(4); + JSR(L3); + ALOAD(4); + ATHROW(); + + // L3: First subroutine. + LABEL(L3); + ASTORE(2); + IINC(1, 2); + JSR(L4); + PUSH(); + PUSH(); + RET(2); + + // L5: Second exception handler. + LABEL(L5); + ASTORE(5); + JSR(L4); + ALOAD(5); + ATHROW(); + + // L4: Second subroutine. + LABEL(L4); + ASTORE(3); + PUSH(); + PUSH(); + IINC(1, 3); + RET(3); + + // L1: On normal exit, try block jumps here. + LABEL(L1); + RETURN(); + + TRYCATCH(L0, L2, L2); + TRYCATCH(L3, L5, L5); + + assertMaxs(5, 6); + } + + /** + * This tests a subroutine which has no ret statement, but ends in a "return" instead. + * + *

We structure this as a try/finally with a break in the finally. Because the while loop is + * infinite, it's clear from the byte code that the only path which reaches the RETURN instruction + * is through the subroutine. + * + *

+   * public void a1() {
+   *     int a = 0;
+   *     while (true) {
+   *         try {
+   *             a += 1;
+   *         } finally {
+   *             a += 2;
+   *             break;
+   *         }
+   *     }
+   * }
+   * 
+ */ + @Test + public void testSubroutineWithNoRet() { + Label L0 = new Label(); + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + Label L4 = new Label(); + + ICONST_0(); + ISTORE(1); + + // L0: while loop header/try block. + LABEL(L0); + IINC(1, 1); + JSR(L1); + GOTO(L2); + + // L3: implicit catch block. + LABEL(L3); + ASTORE(2); + JSR(L1); + PUSH(); + PUSH(); + ALOAD(2); + ATHROW(); + + // L1: subroutine which does not return. + LABEL(L1); + ASTORE(3); + IINC(1, 2); + GOTO(L4); + + // L2: end of the loop, goes back to the top. + LABEL(L2); + GOTO(L0); + + // L4: + LABEL(L4); + RETURN(); + + TRYCATCH(L0, L3, L3); + + assertMaxs(1, 4); + } + + /** + * This tests a subroutine which has no ret statement, but ends in a "return" instead. + * + *
+   *   ACONST_NULL
+   *   JSR L0
+   * L0:
+   *   ASTORE 0
+   *   ASTORE 0
+   *   RETURN
+   * 
+ */ + @Test + public void testSubroutineWithNoRet2() { + Label L0 = new Label(); + Label L1 = new Label(); + + ACONST_NULL(); + JSR(L0); + NOP(); + LABEL(L0); + ASTORE(0); + ASTORE(0); + RETURN(); + LABEL(L1); + methodVisitor.visitLocalVariable("i", "I", null, L0, L1, 1); + + assertMaxs(2, 2); + } + + /** + * This tests a subroutine which has no ret statement, but instead exits implicitely by branching + * to code which is not part of the subroutine. (Sadly, this is legal) + * + *

We structure this as a try/finally in a loop with a break in the finally. The loop is not + * trivially infinite, so the RETURN statement is reachable both from the JSR subroutine and from + * the main entry point. + * + *

+   * public void a1() {
+   *     int a = 0;
+   *     while (null == null) {
+   *         try {
+   *             a += 1;
+   *         } finally {
+   *             a += 2;
+   *             break;
+   *         }
+   *     }
+   * }
+   * 
+ */ + @Test + public void testImplicitExit() { + Label L0 = new Label(); + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + Label L4 = new Label(); + Label L5 = new Label(); + + ICONST_0(); + ISTORE(1); + + // L5: while loop header. + LABEL(L5); + ACONST_NULL(); + IFNONNULL(L4); + + // L0: try block. + LABEL(L0); + IINC(1, 1); + JSR(L1); + GOTO(L2); + + // L3: implicit catch block. + LABEL(L3); + ASTORE(2); + JSR(L1); + ALOAD(2); + PUSH(); + PUSH(); + ATHROW(); + + // L1: subroutine which does not return. + LABEL(L1); + ASTORE(3); + IINC(1, 2); + GOTO(L4); + + // L2: end of the loop, goes back to the top. + LABEL(L2); + GOTO(L0); + + // L4: + LABEL(L4); + RETURN(); + + TRYCATCH(L0, L3, L3); + + assertMaxs(1, 4); + } + + /** + * Tests a nested try/finally with implicit exit from one subroutine to the other subroutine. + * Equivalent to the following java code: + * + *
+   * void m(boolean b) {
+   *     try {
+   *         return;
+   *     } finally {
+   *         while (b) {
+   *             try {
+   *                 return;
+   *             } finally {
+   *                 // NOTE --- this break avoids the second return above (weird)
+   *                 if (b)
+   *                     break;
+   *             }
+   *         }
+   *     }
+   * }
+   * 
+ * + * This example is from the paper, "Subroutine Inlining and Bytecode Abstraction to Simplify + * Static and Dynamic Analysis" by Cyrille Artho and Armin Biere. + */ + @Test + public void testImplicitExitToAnotherSubroutine() { + Label T1 = new Label(); + Label C1 = new Label(); + Label S1 = new Label(); + Label L = new Label(); + Label C2 = new Label(); + Label S2 = new Label(); + Label W = new Label(); + Label X = new Label(); + + // Variable numbers: + int b = 1; + int e1 = 2; + int e2 = 3; + int r1 = 4; + int r2 = 5; + + ICONST_0(); + ISTORE(1); + + // T1: first try. + LABEL(T1); + JSR(S1); + RETURN(); + + // C1: exception handler for first try. + LABEL(C1); + ASTORE(e1); + JSR(S1); + PUSH(); + PUSH(); + ALOAD(e1); + ATHROW(); + + // S1: first finally handler. + LABEL(S1); + ASTORE(r1); + PUSH(); + PUSH(); + GOTO(W); + + // L: body of while loop, also second try. + LABEL(L); + JSR(S2); + RETURN(); + + // C2: exception handler for second try. + LABEL(C2); + ASTORE(e2); + PUSH(); + PUSH(); + JSR(S2); + ALOAD(e2); + ATHROW(); + + // S2: second finally handler. + LABEL(S2); + ASTORE(r2); + ILOAD(b); + IFNE(X); + RET(r2); + + // W: test for the while loop. + LABEL(W); + ILOAD(b); + IFNE(L); // falls through to X. + + // X: exit from finally{} block. + LABEL(X); + RET(r1); + + TRYCATCH(T1, C1, C1); + TRYCATCH(L, C2, C2); + + assertMaxs(5, 6); + } + + @Test + public void testImplicitExitToAnotherSubroutine2() { + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + + ICONST_0(); + ISTORE(1); + JSR(L1); + RETURN(); + + LABEL(L1); + ASTORE(2); + JSR(L2); + GOTO(L3); + + LABEL(L2); + ASTORE(3); + ILOAD(1); + IFNE(L3); + RET(3); + + LABEL(L3); + RET(2); + + assertMaxs(1, 4); + } + + /** + * This tests a simple subroutine where the control flow jumps back and forth between the + * subroutine and the caller. + * + *

This would not normally be produced by a java compiler. + */ + @Test + public void testInterleavedCode() { + Label L1 = new Label(); + Label L2 = new Label(); + Label L3 = new Label(); + Label L4 = new Label(); + + ICONST_0(); + ISTORE(1); + JSR(L1); + GOTO(L2); + + // L1: subroutine 1. + LABEL(L1); + ASTORE(2); + IINC(1, 1); + GOTO(L3); + + // L2: second part of main subroutine. + LABEL(L2); + IINC(1, 2); + GOTO(L4); + + // L3: second part of subroutine 1. + LABEL(L3); + IINC(1, 4); + PUSH(); + PUSH(); + RET(2); + + // L4: third part of main subroutine. + LABEL(L4); + PUSH(); + PUSH(); + RETURN(); + + assertMaxs(4, 3); + } + + /** + * Tests a nested try/finally with implicit exit from one subroutine to the other subroutine, and + * with a surrounding try/catch thrown in the mix. Equivalent to the following java code: + * + *

+   * void m(int b) {
+   *     try {
+   *         try {
+   *             return;
+   *         } finally {
+   *             while (b) {
+   *                 try {
+   *                     return;
+   *                 } finally {
+   *                     // NOTE --- this break avoids the second return above
+   *                     // (weird)
+   *                     if (b)
+   *                         break;
+   *                 }
+   *             }
+   *         }
+   *     } catch (Exception e) {
+   *         b += 3;
+   *         return;
+   *     }
+   * }
+   * 
+ */ + @Test + public void testImplicitExitInTryCatch() { + Label T1 = new Label(); + Label C1 = new Label(); + Label S1 = new Label(); + Label L = new Label(); + Label C2 = new Label(); + Label S2 = new Label(); + Label W = new Label(); + Label X = new Label(); + Label OC = new Label(); + + // Variable numbers. + int b = 1; + int e1 = 2; + int e2 = 3; + int r1 = 4; + int r2 = 5; + + ICONST_0(); + ISTORE(1); + + // T1: first try. + LABEL(T1); + JSR(S1); + RETURN(); + + // C1: exception handler for first try. + LABEL(C1); + ASTORE(e1); + JSR(S1); + ALOAD(e1); + ATHROW(); + + // S1: first finally handler. + LABEL(S1); + ASTORE(r1); + GOTO(W); + + // L: body of while loop, also second try. + LABEL(L); + JSR(S2); + PUSH(); + PUSH(); + RETURN(); + + // C2: exception handler for second try. + LABEL(C2); + ASTORE(e2); + JSR(S2); + ALOAD(e2); + ATHROW(); + + // S2: second finally handler. + LABEL(S2); + ASTORE(r2); + ILOAD(b); + IFNE(X); + PUSH(); + PUSH(); + RET(r2); + + // W: test for the while loop. + LABEL(W); + ILOAD(b); + IFNE(L); // falls through to X. + + // X: exit from finally{} block. + LABEL(X); + RET(r1); + + // OC: outermost catch. + LABEL(OC); + IINC(b, 3); + RETURN(); + + TRYCATCH(T1, C1, C1); + TRYCATCH(L, C2, C2); + TRYCATCH(T1, OC, OC); + + assertMaxs(4, 6); + } + + /** + * Tests an example coming from distilled down version of + * com/sun/corba/ee/impl/protocol/CorbaClientDelegateImpl from GlassFish 2. See issue #317823. + */ + @Test + public void testGlassFish2CorbaClientDelegateImplExample() { + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + Label l3 = new Label(); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + Label l7 = new Label(); + Label l8 = new Label(); + Label l9 = new Label(); + Label l10 = new Label(); + Label l11 = new Label(); + Label l12 = new Label(); + + LABEL(l0); + JSR(l9); + LABEL(l1); + GOTO(l10); + LABEL(l2); + POP(); + JSR(l9); + LABEL(l3); + ACONST_NULL(); + ATHROW(); + LABEL(l9); + ASTORE(1); + RET(1); + LABEL(l10); + ACONST_NULL(); + ACONST_NULL(); + ACONST_NULL(); + POP(); + POP(); + POP(); + LABEL(l4); + GOTO(l11); + LABEL(l5); + POP(); + GOTO(l11); + ACONST_NULL(); + ATHROW(); + LABEL(l11); + ICONST_0(); + IFNE(l0); + JSR(l12); + LABEL(l6); + RETURN(); + LABEL(l7); + POP(); + JSR(l12); + LABEL(l8); + ACONST_NULL(); + ATHROW(); + LABEL(l12); + ASTORE(2); + RET(2); + + TRYCATCH(l0, l1, l2); + TRYCATCH(l2, l3, l2); + TRYCATCH(l0, l4, l5); + TRYCATCH(l0, l6, l7); + TRYCATCH(l7, l8, l7); + + assertMaxs(3, 3); + } + + protected void assertMaxs(final int maxStack, final int maxLocals) { + methodVisitor.visitMaxs(maxStack, maxLocals); + methodVisitor.visitEnd(); + classWriter.visitEnd(); + byte[] classFile = classWriter.toByteArray(); + ClassReader classReader = new ClassReader(classFile); + classReader.accept( + new ClassVisitor(Opcodes.ASM5) { + @Override + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) { + if (name.equals("m")) { + return new MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) { + @Override + public void visitEnd() { + Analyzer a = new Analyzer(new BasicInterpreter()); + try { + Frame[] frames = a.analyze("C", this); + int mStack = 0; + int mLocals = 0; + for (int i = 0; i < frames.length; ++i) { + if (frames[i] != null) { + mStack = Math.max(mStack, frames[i].getStackSize()); + mLocals = Math.max(mLocals, frames[i].getLocals()); + } + } + assertEquals(maxStack, mStack, "maxStack"); + assertEquals(maxLocals, mLocals, "maxLocals"); + } catch (Exception e) { + fail(e.getMessage()); + } + } + }; + } else { + return null; + } + } + }, + 0); + + try { + TestClassLoader loader = new TestClassLoader(); + loader.defineClass("C", classFile).newInstance(); + } catch (Throwable t) { + fail(t.getMessage()); + } + } +} diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/BasicInterpreterTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/BasicInterpreterTest.java new file mode 100644 index 000000000..f2ceb1239 --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/BasicInterpreterTest.java @@ -0,0 +1,160 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static java.time.Duration.ofSeconds; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.FileInputStream; +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.test.AsmTest; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * BasicInterpreter tests. + * + * @author Eric Bruneton + */ +public class BasicInterpreterTest extends AsmTest { + + @Test + public void testConstructor() { + assertThrows(IllegalStateException.class, () -> new BasicInterpreter() {}); + } + + /** + * Tests that stack map frames are correctly merged when a JSR instruction can be reached from two + * different control flow paths, with different local variable types (#316204). + * + * @throws IOException + * @throws AnalyzerException + */ + @Test + public void testMergeWithJsrReachableFromTwoDifferentPaths() + throws IOException, AnalyzerException { + ClassReader classReader = + new ClassReader(new FileInputStream("src/test/resources/Issue316204.class")); + ClassNode classNode = new ClassNode(); + classReader.accept(classNode, 0); + Analyzer analyzer = new Analyzer<>(new BasicInterpreter()); + analyzer.analyze(classNode.name, getMethod(classNode, "basicStopBundles")); + assertEquals("RIR..... ", analyzer.getFrames()[104].toString()); + } + + /** + * Tests that the analyzer does not loop infinitely, even if the {@link Interpreter#merge} method + * does not follow its required contract (namely that if the merge result is equal to the first + * argument, the first argument should be returned - see #316326). + * + * @throws AnalyzerException + */ + @Test + public void testAnalyzeWithBadInterpreter() throws AnalyzerException { + ClassNode classNode = new ClassNode(); + new ClassReader(PrecompiledClass.JDK8_ALL_FRAMES.getBytes()).accept(classNode, 0); + for (MethodNode methodNode : classNode.methods) { + Analyzer analyzer = + new Analyzer( + new BasicInterpreter(Opcodes.ASM7_EXPERIMENTAL) { + @Override + public BasicValue merge(final BasicValue value1, final BasicValue value2) { + return new BasicValue(super.merge(value1, value2).getType()); + } + }); + assertTimeoutPreemptively(ofSeconds(1), () -> analyzer.analyze("Test", methodNode)); + } + } + + /** + * Tests that the precompiled classes can be successfully analyzed with a BasicInterpreter, and + * that Analyzer can be subclassed to use custom frames. + * + * @throws AnalyzerException + */ + @ParameterizedTest + @MethodSource(ALL_CLASSES_AND_LATEST_API) + public void testAnalyze(final PrecompiledClass classParameter, final Api apiParameter) + throws AnalyzerException { + ClassNode classNode = new ClassNode(); + new ClassReader(classParameter.getBytes()).accept(classNode, 0); + for (MethodNode methodNode : classNode.methods) { + Analyzer analyzer = + new Analyzer(new BasicInterpreter()) { + @Override + protected Frame newFrame(final int nLocals, final int nStack) { + return new CustomFrame(nLocals, nStack); + } + + @Override + protected Frame newFrame(final Frame src) { + return new CustomFrame(src); + } + }; + analyzer.analyze(classNode.name, methodNode); + for (Frame frame : analyzer.getFrames()) { + assertTrue(frame == null || frame instanceof CustomFrame); + } + } + } + + private static MethodNode getMethod(final ClassNode classNode, final String name) { + for (MethodNode methodNode : classNode.methods) { + if (methodNode.name.equals(name)) { + return methodNode; + } + } + return null; + } + + private static class CustomFrame extends Frame { + + CustomFrame(final int nLocals, final int nStack) { + super(nLocals, nStack); + } + + CustomFrame(final Frame frame) { + super(frame); + } + + @Override + public Frame init(final Frame frame) { + assertTrue(frame instanceof CustomFrame); + return super.init(frame); + } + } +} diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/BasicVerifierTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/BasicVerifierTest.java new file mode 100644 index 000000000..eb5b202b4 --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/BasicVerifierTest.java @@ -0,0 +1,68 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.test.AsmTest; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * BasicVerifier tests. + * + * @author Eric Bruneton + */ +public class BasicVerifierTest extends AsmTest { + + @Test + public void testConstructor() { + assertThrows(IllegalStateException.class, () -> new BasicVerifier() {}); + } + + /** + * Tests that the precompiled classes can be successfully analyzed with a BasicVerifier. + * + * @throws AnalyzerException + */ + @ParameterizedTest + @MethodSource(ALL_CLASSES_AND_LATEST_API) + public void testAnalyze(final PrecompiledClass classParameter, final Api apiParameter) + throws AnalyzerException { + ClassNode classNode = new ClassNode(); + new ClassReader(classParameter.getBytes()).accept(classNode, 0); + for (MethodNode methodNode : classNode.methods) { + Analyzer analyzer = new Analyzer(new BasicVerifier()); + analyzer.analyze(classNode.name, methodNode); + } + } +} diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SimpleVerifierTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SimpleVerifierTest.java new file mode 100644 index 000000000..7483386fd --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SimpleVerifierTest.java @@ -0,0 +1,535 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Label; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.test.AsmTest; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * SimpleVerifier tests. + * + * @author Eric Bruneton + */ +public class SimpleVerifierTest extends AsmTest implements Opcodes { + + private Analyzer anaylzer; + + private MethodNode methodNode; + + @BeforeEach + public void setUp() { + Type baseType = Type.getType("LC;"); + Type superType = Type.getType("Ljava/lang/Number;"); + anaylzer = new Analyzer(new SimpleVerifier(baseType, superType, false)); + methodNode = new MethodNode(ACC_PUBLIC, "m", "()V", null, null); + } + + private void assertValid() throws AnalyzerException { + methodNode.visitInsn(RETURN); + methodNode.visitMaxs(10, 10); + anaylzer.analyze("C", methodNode); + Frame[] frames = anaylzer.getFrames(); + for (int i = 0; i < frames.length; ++i) { + if (frames[i] != null) { + frames[i].toString(); + } + } + anaylzer.getHandlers(0); + } + + private void assertInvalid() { + methodNode.visitInsn(RETURN); + methodNode.visitMaxs(10, 10); + assertThrows(AnalyzerException.class, () -> anaylzer.analyze("C", methodNode)); + } + + @Test + public void testConstructor() { + assertThrows(IllegalStateException.class, () -> new SimpleVerifier() {}); + } + + @Test + public void testInvalidOpcode() { + methodNode.visitInsn(-1); + assertInvalid(); + } + + @Test + public void testInvalidPop() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(POP); + assertInvalid(); + } + + @Test + public void testInvalidPop2() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(POP2); + assertInvalid(); + } + + @Test + public void testInvalidDup() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(DUP); + assertInvalid(); + } + + @Test + public void testInvalidDupx1() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(DUP_X1); + assertInvalid(); + } + + @Test + public void testInvalidDupx2() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(DUP_X2); + assertInvalid(); + } + + @Test + public void testInvalidDup2() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(DUP2); + assertInvalid(); + } + + @Test + public void testInvalidDup2x1() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(DUP2_X1); + assertInvalid(); + } + + @Test + public void testInvalidDup2x2() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(DUP2_X2); + assertInvalid(); + } + + @Test + public void testInvalidSwap() { + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(SWAP); + assertInvalid(); + } + + @Test + public void testInvalidGetLocal() { + methodNode.visitVarInsn(ALOAD, 10); + assertInvalid(); + } + + @Test + public void testInvalidSetLocal() { + methodNode.visitInsn(ACONST_NULL); + methodNode.visitVarInsn(ASTORE, 10); + assertInvalid(); + } + + @Test + public void testInvalidEmptyStack() { + methodNode.visitInsn(POP); + assertInvalid(); + } + + @Test + public void testInvalidFullStack() { + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + assertInvalid(); + } + + @Test + public void testInconsistentStackHeights() { + Label ifLabel = new Label(); + methodNode.visitInsn(ICONST_0); + methodNode.visitJumpInsn(IFEQ, ifLabel); + methodNode.visitInsn(ICONST_0); + methodNode.visitLabel(ifLabel); + assertInvalid(); + } + + @Test + public void testInvalidNewArray() { + methodNode.visitInsn(ICONST_1); + methodNode.visitIntInsn(NEWARRAY, -1); + assertInvalid(); + } + + @Test + public void testInvalidAload() { + methodNode.visitInsn(ICONST_0); + methodNode.visitVarInsn(ISTORE, 1); + methodNode.visitVarInsn(ALOAD, 1); + assertInvalid(); + } + + @Test + public void testInvalidAstore() { + methodNode.visitInsn(ICONST_0); + methodNode.visitVarInsn(ASTORE, 1); + assertInvalid(); + } + + @Test + public void testInvalidIstore() { + methodNode.visitInsn(ACONST_NULL); + methodNode.visitVarInsn(ISTORE, 1); + assertInvalid(); + } + + @Test + public void testInvalidCheckcast() { + methodNode.visitInsn(ICONST_0); + methodNode.visitTypeInsn(CHECKCAST, "java/lang/String"); + assertInvalid(); + } + + @Test + public void testInvalidArraylength() { + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ARRAYLENGTH); + assertInvalid(); + } + + @Test + public void testInvalidAthrow() { + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ATHROW); + assertInvalid(); + } + + @Test + public void testInvalidIneg() { + methodNode.visitInsn(FCONST_0); + methodNode.visitInsn(INEG); + assertInvalid(); + } + + @Test + public void testInvalidIadd() { + methodNode.visitInsn(FCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(IADD); + assertInvalid(); + } + + @Test + public void testInvalidIsub() { + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(FCONST_0); + methodNode.visitInsn(ISUB); + assertInvalid(); + } + + @Test + public void testInvalidIastore() { + methodNode.visitInsn(ICONST_1); + methodNode.visitIntInsn(NEWARRAY, T_INT); + methodNode.visitInsn(FCONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(IASTORE); + assertInvalid(); + } + + @Test + public void testInvalidFastore() { + methodNode.visitInsn(ICONST_1); + methodNode.visitIntInsn(NEWARRAY, T_FLOAT); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(FASTORE); + assertInvalid(); + } + + @Test + public void testInvalidLastore() { + methodNode.visitInsn(ICONST_1); + methodNode.visitInsn(ICONST_0); + methodNode.visitInsn(LCONST_0); + methodNode.visitInsn(LASTORE); + assertInvalid(); + } + + @Test + public void testInvalidMultianewarray() { + methodNode.visitInsn(FCONST_1); + methodNode.visitInsn(ICONST_2); + methodNode.visitMultiANewArrayInsn("[[I", 2); + assertInvalid(); + } + + @Test + public void testInvalidInvokevirtual() { + methodNode.visitInsn(ACONST_NULL); + methodNode.visitTypeInsn(CHECKCAST, "java/lang/Object"); + methodNode.visitMethodInsn(INVOKEVIRTUAL, "java/util/ArrayList", "size", "()I", false); + assertInvalid(); + } + + @Test + public void testInvalidInvokeinterface() { + methodNode.visitInsn(ACONST_NULL); + methodNode.visitTypeInsn(CHECKCAST, "java/util/List"); + methodNode.visitInsn(FCONST_0); + methodNode.visitMethodInsn( + INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true); + assertInvalid(); + } + + @Test + public void testInvalidRet() { + methodNode.visitVarInsn(RET, 1); + assertInvalid(); + } + + @Test + public void testInvalidFalloff() { + methodNode.visitMaxs(10, 10); + assertThrows(AnalyzerException.class, () -> anaylzer.analyze("C", methodNode)); + } + + @Test + public void testInvalidSubroutineFalloff() { + Label gotoLabel = new Label(); + Label jsrLabel = new Label(); + methodNode.visitJumpInsn(GOTO, gotoLabel); + methodNode.visitLabel(jsrLabel); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitVarInsn(RET, 1); + methodNode.visitLabel(gotoLabel); + methodNode.visitJumpInsn(JSR, jsrLabel); + methodNode.visitMaxs(10, 10); + assertThrows(AnalyzerException.class, () -> anaylzer.analyze("C", methodNode)); + } + + @Test + public void testNestedSubroutines() throws AnalyzerException { + Label subroutine1Label = new Label(); + Label subroutine2Label = new Label(); + methodNode.visitJumpInsn(JSR, subroutine1Label); + methodNode.visitInsn(RETURN); + methodNode.visitLabel(subroutine1Label); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitJumpInsn(JSR, subroutine2Label); + methodNode.visitJumpInsn(JSR, subroutine2Label); + methodNode.visitVarInsn(RET, 1); + methodNode.visitLabel(subroutine2Label); + methodNode.visitVarInsn(ASTORE, 2); + methodNode.visitVarInsn(RET, 2); + assertValid(); + } + + @Test + public void testSubroutineLocalsAccess() throws AnalyzerException { + methodNode.visitCode(); + Label startLabel = new Label(); + Label exceptionHandler1Label = new Label(); + Label exceptionHandler2Label = new Label(); + Label subroutineLabel = new Label(); + methodNode.visitTryCatchBlock(startLabel, startLabel, exceptionHandler1Label, null); + methodNode.visitTryCatchBlock( + startLabel, exceptionHandler2Label, exceptionHandler2Label, "java/lang/RuntimeException"); + methodNode.visitLabel(startLabel); + methodNode.visitJumpInsn(JSR, subroutineLabel); + methodNode.visitInsn(RETURN); + methodNode.visitLabel(exceptionHandler1Label); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitJumpInsn(JSR, subroutineLabel); + methodNode.visitVarInsn(ALOAD, 1); + methodNode.visitInsn(ATHROW); + methodNode.visitLabel(subroutineLabel); + methodNode.visitVarInsn(ASTORE, 2); + methodNode.visitInsn(ACONST_NULL); + methodNode.visitVarInsn(ASTORE, 3); + methodNode.visitVarInsn(RET, 2); + methodNode.visitLabel(exceptionHandler2Label); + methodNode.visitVarInsn(ASTORE, 4); + methodNode.visitVarInsn(ALOAD, 4); + methodNode.visitInsn(ATHROW); + assertValid(); + } + + @Disabled("TODO currently Analyzer can not detect this situation") + @Test + public void testOverlappingSubroutines() { + // The problem is that other overlapping subroutine situations are valid, such as + // when a nested subroutine implicitly returns to its parent subroutine, without a RET. + Label subroutine1Label = new Label(); + Label subroutine2Label = new Label(); + Label endSubroutineLabel = new Label(); + methodNode.visitJumpInsn(JSR, subroutine1Label); + methodNode.visitJumpInsn(JSR, subroutine2Label); + methodNode.visitInsn(RETURN); + methodNode.visitLabel(subroutine1Label); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitJumpInsn(GOTO, endSubroutineLabel); + methodNode.visitLabel(subroutine2Label); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitLabel(endSubroutineLabel); + methodNode.visitVarInsn(RET, 1); + assertInvalid(); + } + + @Test + public void testMerge() throws AnalyzerException { + Label loopLabel = new Label(); + methodNode.visitVarInsn(ALOAD, 0); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitInsn(ACONST_NULL); + methodNode.visitTypeInsn(CHECKCAST, "java/lang/Number"); + methodNode.visitVarInsn(ASTORE, 2); + methodNode.visitVarInsn(ALOAD, 0); + methodNode.visitVarInsn(ASTORE, 3); + methodNode.visitLabel(loopLabel); + methodNode.visitInsn(ACONST_NULL); + methodNode.visitTypeInsn(CHECKCAST, "java/lang/Number"); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitVarInsn(ALOAD, 0); + methodNode.visitVarInsn(ASTORE, 2); + methodNode.visitInsn(ACONST_NULL); + methodNode.visitTypeInsn(CHECKCAST, "java/lang/Integer"); + methodNode.visitVarInsn(ASTORE, 3); + methodNode.visitJumpInsn(GOTO, loopLabel); + assertValid(); + } + + @Test + public void testClassNotFound() { + Label loopLabel = new Label(); + methodNode.visitVarInsn(ALOAD, 0); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitLabel(loopLabel); + methodNode.visitInsn(ACONST_NULL); + methodNode.visitTypeInsn(CHECKCAST, "D"); + methodNode.visitVarInsn(ASTORE, 1); + methodNode.visitJumpInsn(GOTO, loopLabel); + methodNode.visitMaxs(10, 10); + assertThrows(Exception.class, () -> anaylzer.analyze("C", methodNode)); + } + + @Test + void testIsAssignableFrom() { + Type baseType = Type.getObjectType("C"); + Type superType = Type.getObjectType("D"); + Type interfaceType = Type.getObjectType("I"); + new SimpleVerifier(ASM7_EXPERIMENTAL, baseType, superType, Arrays.asList(interfaceType), false) { + + void test() { + assertTrue(isAssignableFrom(baseType, baseType)); + assertTrue(isAssignableFrom(superType, baseType)); + assertTrue(isAssignableFrom(interfaceType, baseType)); + } + + @Override + protected Class getClass(final Type type) { + // Return dummy classes, to make sure isAssignable in test() does not rely on them. + if (type == baseType) return int.class; + if (type == superType) return float.class; + if (type == interfaceType) return double.class; + return super.getClass(type); + } + }.test(); + + new SimpleVerifier(ASM7_EXPERIMENTAL, interfaceType, null, null, true) { + + void test() { + assertTrue(isAssignableFrom(interfaceType, baseType)); + assertTrue(isAssignableFrom(interfaceType, Type.getObjectType("[I"))); + assertFalse(isAssignableFrom(interfaceType, Type.INT_TYPE)); + } + + @Override + protected Type getSuperClass(final Type type) { + return superType; + } + }.test(); + } + + /** + * Tests that the precompiled classes can be successfully analyzed with a SimpleVerifier. + * + * @throws AnalyzerException + */ + @ParameterizedTest + @MethodSource(ALL_CLASSES_AND_LATEST_API) + public void testAnalyze(final PrecompiledClass classParameter, final Api apiParameter) + throws AnalyzerException { + ClassNode classNode = new ClassNode(); + new ClassReader(classParameter.getBytes()).accept(classNode, 0); + for (MethodNode methodNode : classNode.methods) { + Analyzer analyzer = + new Analyzer( + new SimpleVerifier( + Type.getObjectType(classNode.name), + Type.getObjectType(classNode.superName), + (classNode.access & Opcodes.ACC_INTERFACE) != 0)); + analyzer.analyze(classNode.name, methodNode); + } + } +} diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SmallSetTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SmallSetTest.java new file mode 100644 index 000000000..85a397dc1 --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SmallSetTest.java @@ -0,0 +1,121 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; + +import org.junit.jupiter.api.Test; + +/** + * SmallSet tests. + * + * @author Eric Bruneton + */ +public class SmallSetTest { + + private static final Object ELEMENT1 = new Object(); + private static final Object ELEMENT2 = new Object(); + private static final Object ELEMENT3 = new Object(); + private static final Object ELEMENT4 = new Object(); + + @Test + public void testUnion1() { + SmallSet set1 = new SmallSet(ELEMENT1); + SmallSet set2 = new SmallSet(ELEMENT1); + Set union1 = set1.union(set2); + Set union2 = set2.union(set1); + assertEquals(union1, union2); + assertEquals(union1, new HashSet(Arrays.asList(ELEMENT1))); + } + + @Test + public void testUnion2() { + SmallSet set1 = newSmallSet(ELEMENT1, ELEMENT2); + SmallSet set2 = new SmallSet(ELEMENT1); + Set union1 = set1.union(set2); + Set union2 = set2.union(set1); + assertEquals(union1, union2); + assertEquals(union1, new HashSet(Arrays.asList(ELEMENT1, ELEMENT2))); + } + + @Test + public void testUnion2EqualSets() { + SmallSet set1 = newSmallSet(ELEMENT1, ELEMENT2); + SmallSet set2 = newSmallSet(ELEMENT2, ELEMENT1); + Set union1 = set1.union(set2); + Set union2 = set2.union(set1); + assertEquals(union1, union2); + assertEquals(union1, new HashSet(Arrays.asList(ELEMENT1, ELEMENT2))); + } + + @Test + public void testUnion3() { + SmallSet set1 = newSmallSet(ELEMENT1, ELEMENT2); + SmallSet set2 = new SmallSet(ELEMENT3); + Set union1 = set1.union(set2); + Set union2 = set2.union(set1); + assertEquals(union1, union2); + assertEquals(union1, new HashSet(Arrays.asList(ELEMENT1, ELEMENT2, ELEMENT3))); + } + + @Test + public void testUnion4() { + SmallSet set1 = newSmallSet(ELEMENT1, ELEMENT2); + SmallSet set2 = newSmallSet(ELEMENT3, ELEMENT4); + Set union1 = set1.union(set2); + Set union2 = set2.union(set1); + assertEquals(union1, union2); + assertEquals( + union1, new HashSet(Arrays.asList(ELEMENT1, ELEMENT2, ELEMENT3, ELEMENT4))); + } + + @Test + public void testIterator() { + Iterator iterator = newSmallSet(ELEMENT1, ELEMENT2).iterator(); + assertTrue(iterator.hasNext()); + assertEquals(ELEMENT1, iterator.next()); + assertTrue(iterator.hasNext()); + assertEquals(ELEMENT2, iterator.next()); + assertFalse(iterator.hasNext()); + assertThrows(NoSuchElementException.class, () -> iterator.next()); + assertThrows(UnsupportedOperationException.class, () -> iterator.remove()); + } + + private SmallSet newSmallSet(Object element1, Object element2) { + return (SmallSet) new SmallSet(element1).union(new SmallSet(element2)); + } +} diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SourceInterpreterTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SourceInterpreterTest.java new file mode 100644 index 000000000..123c10413 --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/SourceInterpreterTest.java @@ -0,0 +1,68 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.test.AsmTest; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +/** + * SourceInterpreter tests. + * + * @author Eric Bruneton + */ +public class SourceInterpreterTest extends AsmTest { + + @Test + public void testConstructor() { + assertThrows(IllegalStateException.class, () -> new SourceInterpreter() {}); + } + + /** + * Tests that the precompiled classes can be successfully analyzed with a SourceInterpreter. + * + * @throws AnalyzerException + */ + @ParameterizedTest + @MethodSource(ALL_CLASSES_AND_LATEST_API) + public void testAnalyze(final PrecompiledClass classParameter, final Api apiParameter) + throws AnalyzerException { + ClassNode classNode = new ClassNode(); + new ClassReader(classParameter.getBytes()).accept(classNode, 0); + for (MethodNode methodNode : classNode.methods) { + Analyzer analyzer = new Analyzer(new SourceInterpreter()); + analyzer.analyze(classNode.name, methodNode); + } + } +} diff --git a/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/ValueTest.java b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/ValueTest.java new file mode 100644 index 000000000..d59619da5 --- /dev/null +++ b/asm-analysis/src/test/java/org/objectweb/asm/tree/analysis/ValueTest.java @@ -0,0 +1,80 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.tree.analysis; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.InsnNode; + +/** + * BasicValue and SourceValue tests. + * + * @author Eric Bruneton + */ +public class ValueTest { + + @Test + public void testBasicValue() { + assertTrue(BasicValue.UNINITIALIZED_VALUE.equals(new BasicValue(null))); + assertTrue(BasicValue.INT_VALUE.equals(new BasicValue(Type.INT_TYPE))); + assertTrue(BasicValue.INT_VALUE.equals(BasicValue.INT_VALUE)); + assertFalse(BasicValue.INT_VALUE.equals(new Object())); + + assertTrue(BasicValue.REFERENCE_VALUE.isReference()); + assertTrue(new BasicValue(Type.getObjectType("[I")).isReference()); + assertFalse(BasicValue.UNINITIALIZED_VALUE.isReference()); + assertFalse(BasicValue.INT_VALUE.isReference()); + + assertEquals(0, BasicValue.UNINITIALIZED_VALUE.hashCode()); + assertNotEquals(0, BasicValue.INT_VALUE.hashCode()); + + assertEquals(".", BasicValue.UNINITIALIZED_VALUE.toString()); + assertEquals("A", BasicValue.RETURNADDRESS_VALUE.toString()); + assertEquals("R", BasicValue.REFERENCE_VALUE.toString()); + assertEquals("LI;", new BasicValue(Type.getObjectType("I")).toString()); + } + + @Test + public void testSourceValue() { + assertEquals(2, new SourceValue(2).getSize()); + + assertTrue(new SourceValue(1).equals(new SourceValue(1))); + assertFalse(new SourceValue(1).equals(new SourceValue(1, new InsnNode(Opcodes.NOP)))); + assertFalse(new SourceValue(1).equals(new SourceValue(2))); + assertFalse(new SourceValue(1).equals(null)); + + assertEquals(0, new SourceValue(1).hashCode()); + assertNotEquals(0, new SourceValue(1, new InsnNode(Opcodes.NOP)).hashCode()); + } +} diff --git a/asm-analysis/src/test/resources/Issue316204.class b/asm-analysis/src/test/resources/Issue316204.class new file mode 100644 index 000000000..964f522df Binary files /dev/null and b/asm-analysis/src/test/resources/Issue316204.class differ diff --git a/asm-analysis/src/test/resources/sigtest-4.0.txt b/asm-analysis/src/test/resources/sigtest-4.0.txt new file mode 100644 index 000000000..95d44cc79 --- /dev/null +++ b/asm-analysis/src/test/resources/sigtest-4.0.txt @@ -0,0 +1,436 @@ +#Signature file v4.1 +#Version 4.0 + +CLSS public abstract interface java.io.Serializable + +CLSS public java.lang.Exception +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +supr java.lang.Throwable +hfds serialVersionUID + +CLSS public java.lang.Object +cons public init() +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException +meth protected void finalize() throws java.lang.Throwable +meth public boolean equals(java.lang.Object) +meth public final java.lang.Class getClass() +meth public final void notify() +meth public final void notifyAll() +meth public final void wait() throws java.lang.InterruptedException +meth public final void wait(long) throws java.lang.InterruptedException +meth public final void wait(long,int) throws java.lang.InterruptedException +meth public int hashCode() +meth public java.lang.String toString() + +CLSS public java.lang.Throwable +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +intf java.io.Serializable +meth public final java.lang.Throwable[] getSuppressed() +meth public final void addSuppressed(java.lang.Throwable) +meth public java.lang.StackTraceElement[] getStackTrace() +meth public java.lang.String getLocalizedMessage() +meth public java.lang.String getMessage() +meth public java.lang.String toString() +meth public java.lang.Throwable fillInStackTrace() +meth public java.lang.Throwable getCause() +meth public java.lang.Throwable initCause(java.lang.Throwable) +meth public void printStackTrace() +meth public void printStackTrace(java.io.PrintStream) +meth public void printStackTrace(java.io.PrintWriter) +meth public void setStackTrace(java.lang.StackTraceElement[]) +supr java.lang.Object +hfds CAUSE_CAPTION,EMPTY_THROWABLE_ARRAY,NULL_CAUSE_MESSAGE,SELF_SUPPRESSION_MESSAGE,SUPPRESSED_CAPTION,SUPPRESSED_SENTINEL,UNASSIGNED_STACK,backtrace,cause,detailMessage,serialVersionUID,stackTrace,suppressedExceptions +hcls PrintStreamOrWriter,SentinelHolder,WrappedPrintStream,WrappedPrintWriter + +CLSS public abstract interface org.objectweb.asm.Opcodes +fld public final static int AALOAD = 50 +fld public final static int AASTORE = 83 +fld public final static int ACC_ABSTRACT = 1024 +fld public final static int ACC_ANNOTATION = 8192 +fld public final static int ACC_BRIDGE = 64 +fld public final static int ACC_DEPRECATED = 131072 +fld public final static int ACC_ENUM = 16384 +fld public final static int ACC_FINAL = 16 +fld public final static int ACC_INTERFACE = 512 +fld public final static int ACC_NATIVE = 256 +fld public final static int ACC_PRIVATE = 2 +fld public final static int ACC_PROTECTED = 4 +fld public final static int ACC_PUBLIC = 1 +fld public final static int ACC_STATIC = 8 +fld public final static int ACC_STRICT = 2048 +fld public final static int ACC_SUPER = 32 +fld public final static int ACC_SYNCHRONIZED = 32 +fld public final static int ACC_SYNTHETIC = 4096 +fld public final static int ACC_TRANSIENT = 128 +fld public final static int ACC_VARARGS = 128 +fld public final static int ACC_VOLATILE = 64 +fld public final static int ACONST_NULL = 1 +fld public final static int ALOAD = 25 +fld public final static int ANEWARRAY = 189 +fld public final static int ARETURN = 176 +fld public final static int ARRAYLENGTH = 190 +fld public final static int ASM4 = 262144 +fld public final static int ASTORE = 58 +fld public final static int ATHROW = 191 +fld public final static int BALOAD = 51 +fld public final static int BASTORE = 84 +fld public final static int BIPUSH = 16 +fld public final static int CALOAD = 52 +fld public final static int CASTORE = 85 +fld public final static int CHECKCAST = 192 +fld public final static int D2F = 144 +fld public final static int D2I = 142 +fld public final static int D2L = 143 +fld public final static int DADD = 99 +fld public final static int DALOAD = 49 +fld public final static int DASTORE = 82 +fld public final static int DCMPG = 152 +fld public final static int DCMPL = 151 +fld public final static int DCONST_0 = 14 +fld public final static int DCONST_1 = 15 +fld public final static int DDIV = 111 +fld public final static int DLOAD = 24 +fld public final static int DMUL = 107 +fld public final static int DNEG = 119 +fld public final static int DREM = 115 +fld public final static int DRETURN = 175 +fld public final static int DSTORE = 57 +fld public final static int DSUB = 103 +fld public final static int DUP = 89 +fld public final static int DUP2 = 92 +fld public final static int DUP2_X1 = 93 +fld public final static int DUP2_X2 = 94 +fld public final static int DUP_X1 = 90 +fld public final static int DUP_X2 = 91 +fld public final static int F2D = 141 +fld public final static int F2I = 139 +fld public final static int F2L = 140 +fld public final static int FADD = 98 +fld public final static int FALOAD = 48 +fld public final static int FASTORE = 81 +fld public final static int FCMPG = 150 +fld public final static int FCMPL = 149 +fld public final static int FCONST_0 = 11 +fld public final static int FCONST_1 = 12 +fld public final static int FCONST_2 = 13 +fld public final static int FDIV = 110 +fld public final static int FLOAD = 23 +fld public final static int FMUL = 106 +fld public final static int FNEG = 118 +fld public final static int FREM = 114 +fld public final static int FRETURN = 174 +fld public final static int FSTORE = 56 +fld public final static int FSUB = 102 +fld public final static int F_APPEND = 1 +fld public final static int F_CHOP = 2 +fld public final static int F_FULL = 0 +fld public final static int F_NEW = -1 +fld public final static int F_SAME = 3 +fld public final static int F_SAME1 = 4 +fld public final static int GETFIELD = 180 +fld public final static int GETSTATIC = 178 +fld public final static int GOTO = 167 +fld public final static int H_GETFIELD = 1 +fld public final static int H_GETSTATIC = 2 +fld public final static int H_INVOKEINTERFACE = 9 +fld public final static int H_INVOKESPECIAL = 7 +fld public final static int H_INVOKESTATIC = 6 +fld public final static int H_INVOKEVIRTUAL = 5 +fld public final static int H_NEWINVOKESPECIAL = 8 +fld public final static int H_PUTFIELD = 3 +fld public final static int H_PUTSTATIC = 4 +fld public final static int I2B = 145 +fld public final static int I2C = 146 +fld public final static int I2D = 135 +fld public final static int I2F = 134 +fld public final static int I2L = 133 +fld public final static int I2S = 147 +fld public final static int IADD = 96 +fld public final static int IALOAD = 46 +fld public final static int IAND = 126 +fld public final static int IASTORE = 79 +fld public final static int ICONST_0 = 3 +fld public final static int ICONST_1 = 4 +fld public final static int ICONST_2 = 5 +fld public final static int ICONST_3 = 6 +fld public final static int ICONST_4 = 7 +fld public final static int ICONST_5 = 8 +fld public final static int ICONST_M1 = 2 +fld public final static int IDIV = 108 +fld public final static int IFEQ = 153 +fld public final static int IFGE = 156 +fld public final static int IFGT = 157 +fld public final static int IFLE = 158 +fld public final static int IFLT = 155 +fld public final static int IFNE = 154 +fld public final static int IFNONNULL = 199 +fld public final static int IFNULL = 198 +fld public final static int IF_ACMPEQ = 165 +fld public final static int IF_ACMPNE = 166 +fld public final static int IF_ICMPEQ = 159 +fld public final static int IF_ICMPGE = 162 +fld public final static int IF_ICMPGT = 163 +fld public final static int IF_ICMPLE = 164 +fld public final static int IF_ICMPLT = 161 +fld public final static int IF_ICMPNE = 160 +fld public final static int IINC = 132 +fld public final static int ILOAD = 21 +fld public final static int IMUL = 104 +fld public final static int INEG = 116 +fld public final static int INSTANCEOF = 193 +fld public final static int INVOKEDYNAMIC = 186 +fld public final static int INVOKEINTERFACE = 185 +fld public final static int INVOKESPECIAL = 183 +fld public final static int INVOKESTATIC = 184 +fld public final static int INVOKEVIRTUAL = 182 +fld public final static int IOR = 128 +fld public final static int IREM = 112 +fld public final static int IRETURN = 172 +fld public final static int ISHL = 120 +fld public final static int ISHR = 122 +fld public final static int ISTORE = 54 +fld public final static int ISUB = 100 +fld public final static int IUSHR = 124 +fld public final static int IXOR = 130 +fld public final static int JSR = 168 +fld public final static int L2D = 138 +fld public final static int L2F = 137 +fld public final static int L2I = 136 +fld public final static int LADD = 97 +fld public final static int LALOAD = 47 +fld public final static int LAND = 127 +fld public final static int LASTORE = 80 +fld public final static int LCMP = 148 +fld public final static int LCONST_0 = 9 +fld public final static int LCONST_1 = 10 +fld public final static int LDC = 18 +fld public final static int LDIV = 109 +fld public final static int LLOAD = 22 +fld public final static int LMUL = 105 +fld public final static int LNEG = 117 +fld public final static int LOOKUPSWITCH = 171 +fld public final static int LOR = 129 +fld public final static int LREM = 113 +fld public final static int LRETURN = 173 +fld public final static int LSHL = 121 +fld public final static int LSHR = 123 +fld public final static int LSTORE = 55 +fld public final static int LSUB = 101 +fld public final static int LUSHR = 125 +fld public final static int LXOR = 131 +fld public final static int MONITORENTER = 194 +fld public final static int MONITOREXIT = 195 +fld public final static int MULTIANEWARRAY = 197 +fld public final static int NEW = 187 +fld public final static int NEWARRAY = 188 +fld public final static int NOP = 0 +fld public final static int POP = 87 +fld public final static int POP2 = 88 +fld public final static int PUTFIELD = 181 +fld public final static int PUTSTATIC = 179 +fld public final static int RET = 169 +fld public final static int RETURN = 177 +fld public final static int SALOAD = 53 +fld public final static int SASTORE = 86 +fld public final static int SIPUSH = 17 +fld public final static int SWAP = 95 +fld public final static int TABLESWITCH = 170 +fld public final static int T_BOOLEAN = 4 +fld public final static int T_BYTE = 8 +fld public final static int T_CHAR = 5 +fld public final static int T_DOUBLE = 7 +fld public final static int T_FLOAT = 6 +fld public final static int T_INT = 10 +fld public final static int T_LONG = 11 +fld public final static int T_SHORT = 9 +fld public final static int V1_1 = 196653 +fld public final static int V1_2 = 46 +fld public final static int V1_3 = 47 +fld public final static int V1_4 = 48 +fld public final static int V1_5 = 49 +fld public final static int V1_6 = 50 +fld public final static int V1_7 = 51 +fld public final static java.lang.Integer DOUBLE +fld public final static java.lang.Integer FLOAT +fld public final static java.lang.Integer INTEGER +fld public final static java.lang.Integer LONG +fld public final static java.lang.Integer NULL +fld public final static java.lang.Integer TOP +fld public final static java.lang.Integer UNINITIALIZED_THIS + +CLSS public org.objectweb.asm.tree.analysis.Analyzer +cons public init(org.objectweb.asm.tree.analysis.Interpreter) +intf org.objectweb.asm.Opcodes +meth protected boolean newControlFlowExceptionEdge(int,int) +meth protected boolean newControlFlowExceptionEdge(int,org.objectweb.asm.tree.TryCatchBlockNode) +meth protected org.objectweb.asm.tree.analysis.Frame newFrame(int,int) +meth protected org.objectweb.asm.tree.analysis.Frame newFrame(org.objectweb.asm.tree.analysis.Frame) +meth protected void init(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth protected void newControlFlowEdge(int,int) +meth public java.util.List getHandlers(int) +meth public org.objectweb.asm.tree.analysis.Frame[] analyze(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Frame[] getFrames() +supr java.lang.Object +hfds frames,handlers,insns,interpreter,n,queue,queued,subroutines,top + +CLSS public org.objectweb.asm.tree.analysis.AnalyzerException +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Object,org.objectweb.asm.tree.analysis.Value) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Throwable) +fld public final org.objectweb.asm.tree.AbstractInsnNode node +supr java.lang.Exception + +CLSS public org.objectweb.asm.tree.analysis.BasicInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.BasicValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.BasicValue +cons public init(org.objectweb.asm.Type) +fld public final static org.objectweb.asm.tree.analysis.BasicValue DOUBLE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue FLOAT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue INT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue LONG_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue REFERENCE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue RETURNADDRESS_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue UNINITIALIZED_VALUE +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public boolean isReference() +meth public int getSize() +meth public int hashCode() +meth public java.lang.String toString() +meth public org.objectweb.asm.Type getType() +supr java.lang.Object +hfds type + +CLSS public org.objectweb.asm.tree.analysis.BasicVerifier +cons protected init(int) +cons public init() +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.BasicInterpreter + +CLSS public org.objectweb.asm.tree.analysis.Frame +cons public init(int,int) +cons public init(org.objectweb.asm.tree.analysis.Frame) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,boolean[]) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,org.objectweb.asm.tree.analysis.Interpreter) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public int getLocals() +meth public int getStackSize() +meth public java.lang.String toString() +meth public org.objectweb.asm.tree.analysis.Frame init(org.objectweb.asm.tree.analysis.Frame) +meth public org.objectweb.asm.tree.analysis.Value getLocal(int) +meth public org.objectweb.asm.tree.analysis.Value getStack(int) +meth public org.objectweb.asm.tree.analysis.Value pop() +meth public void clearStack() +meth public void execute(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Interpreter) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void push(org.objectweb.asm.tree.analysis.Value) +meth public void setLocal(int,org.objectweb.asm.tree.analysis.Value) +meth public void setReturn(org.objectweb.asm.tree.analysis.Value) +supr java.lang.Object +hfds locals,returnValue,top,values + +CLSS public abstract org.objectweb.asm.tree.analysis.Interpreter +cons protected init(int) +fld protected final int api +meth public abstract org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public abstract org.objectweb.asm.tree.analysis.Value naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value newValue(org.objectweb.asm.Type) +meth public abstract org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr java.lang.Object + +CLSS public org.objectweb.asm.tree.analysis.SimpleVerifier +cons protected init(int,org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +cons public init() +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,boolean) +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isAssignableFrom(org.objectweb.asm.Type,org.objectweb.asm.Type) +meth protected boolean isInterface(org.objectweb.asm.Type) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected java.lang.Class getClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.Type getSuperClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public void setClassLoader(java.lang.ClassLoader) +supr org.objectweb.asm.tree.analysis.BasicVerifier +hfds class$java$lang$Object,currentClass,currentClassInterfaces,currentSuperClass,isInterface,loader + +CLSS public org.objectweb.asm.tree.analysis.SourceInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.SourceValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue merge(org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) +meth public org.objectweb.asm.tree.analysis.SourceValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) +meth public org.objectweb.asm.tree.analysis.SourceValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.SourceValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.SourceValue +cons public init(int) +cons public init(int,java.util.Set) +cons public init(int,org.objectweb.asm.tree.AbstractInsnNode) +fld public final int size +fld public final java.util.Set insns +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public int getSize() +meth public int hashCode() +supr java.lang.Object + +CLSS public abstract interface org.objectweb.asm.tree.analysis.Value +meth public abstract int getSize() + diff --git a/asm-analysis/src/test/resources/sigtest-5.0.txt b/asm-analysis/src/test/resources/sigtest-5.0.txt new file mode 100644 index 000000000..6914a11ea --- /dev/null +++ b/asm-analysis/src/test/resources/sigtest-5.0.txt @@ -0,0 +1,440 @@ +#Signature file v4.1 +#Version 5.0 + +CLSS public abstract interface java.io.Serializable + +CLSS public java.lang.Exception +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +supr java.lang.Throwable +hfds serialVersionUID + +CLSS public java.lang.Object +cons public init() +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException +meth protected void finalize() throws java.lang.Throwable +meth public boolean equals(java.lang.Object) +meth public final java.lang.Class getClass() +meth public final void notify() +meth public final void notifyAll() +meth public final void wait() throws java.lang.InterruptedException +meth public final void wait(long) throws java.lang.InterruptedException +meth public final void wait(long,int) throws java.lang.InterruptedException +meth public int hashCode() +meth public java.lang.String toString() + +CLSS public java.lang.Throwable +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +intf java.io.Serializable +meth public final java.lang.Throwable[] getSuppressed() +meth public final void addSuppressed(java.lang.Throwable) +meth public java.lang.StackTraceElement[] getStackTrace() +meth public java.lang.String getLocalizedMessage() +meth public java.lang.String getMessage() +meth public java.lang.String toString() +meth public java.lang.Throwable fillInStackTrace() +meth public java.lang.Throwable getCause() +meth public java.lang.Throwable initCause(java.lang.Throwable) +meth public void printStackTrace() +meth public void printStackTrace(java.io.PrintStream) +meth public void printStackTrace(java.io.PrintWriter) +meth public void setStackTrace(java.lang.StackTraceElement[]) +supr java.lang.Object +hfds CAUSE_CAPTION,EMPTY_THROWABLE_ARRAY,NULL_CAUSE_MESSAGE,SELF_SUPPRESSION_MESSAGE,SUPPRESSED_CAPTION,SUPPRESSED_SENTINEL,UNASSIGNED_STACK,backtrace,cause,detailMessage,serialVersionUID,stackTrace,suppressedExceptions +hcls PrintStreamOrWriter,SentinelHolder,WrappedPrintStream,WrappedPrintWriter + +CLSS public abstract interface org.objectweb.asm.Opcodes +fld public final static int AALOAD = 50 +fld public final static int AASTORE = 83 +fld public final static int ACC_ABSTRACT = 1024 +fld public final static int ACC_ANNOTATION = 8192 +fld public final static int ACC_BRIDGE = 64 +fld public final static int ACC_DEPRECATED = 131072 +fld public final static int ACC_ENUM = 16384 +fld public final static int ACC_FINAL = 16 +fld public final static int ACC_INTERFACE = 512 +fld public final static int ACC_MANDATED = 32768 +fld public final static int ACC_NATIVE = 256 +fld public final static int ACC_PRIVATE = 2 +fld public final static int ACC_PROTECTED = 4 +fld public final static int ACC_PUBLIC = 1 +fld public final static int ACC_STATIC = 8 +fld public final static int ACC_STRICT = 2048 +fld public final static int ACC_SUPER = 32 +fld public final static int ACC_SYNCHRONIZED = 32 +fld public final static int ACC_SYNTHETIC = 4096 +fld public final static int ACC_TRANSIENT = 128 +fld public final static int ACC_VARARGS = 128 +fld public final static int ACC_VOLATILE = 64 +fld public final static int ACONST_NULL = 1 +fld public final static int ALOAD = 25 +fld public final static int ANEWARRAY = 189 +fld public final static int ARETURN = 176 +fld public final static int ARRAYLENGTH = 190 +fld public final static int ASM4 = 262144 +fld public final static int ASM5 = 327680 +fld public final static int ASTORE = 58 +fld public final static int ATHROW = 191 +fld public final static int BALOAD = 51 +fld public final static int BASTORE = 84 +fld public final static int BIPUSH = 16 +fld public final static int CALOAD = 52 +fld public final static int CASTORE = 85 +fld public final static int CHECKCAST = 192 +fld public final static int D2F = 144 +fld public final static int D2I = 142 +fld public final static int D2L = 143 +fld public final static int DADD = 99 +fld public final static int DALOAD = 49 +fld public final static int DASTORE = 82 +fld public final static int DCMPG = 152 +fld public final static int DCMPL = 151 +fld public final static int DCONST_0 = 14 +fld public final static int DCONST_1 = 15 +fld public final static int DDIV = 111 +fld public final static int DLOAD = 24 +fld public final static int DMUL = 107 +fld public final static int DNEG = 119 +fld public final static int DREM = 115 +fld public final static int DRETURN = 175 +fld public final static int DSTORE = 57 +fld public final static int DSUB = 103 +fld public final static int DUP = 89 +fld public final static int DUP2 = 92 +fld public final static int DUP2_X1 = 93 +fld public final static int DUP2_X2 = 94 +fld public final static int DUP_X1 = 90 +fld public final static int DUP_X2 = 91 +fld public final static int F2D = 141 +fld public final static int F2I = 139 +fld public final static int F2L = 140 +fld public final static int FADD = 98 +fld public final static int FALOAD = 48 +fld public final static int FASTORE = 81 +fld public final static int FCMPG = 150 +fld public final static int FCMPL = 149 +fld public final static int FCONST_0 = 11 +fld public final static int FCONST_1 = 12 +fld public final static int FCONST_2 = 13 +fld public final static int FDIV = 110 +fld public final static int FLOAD = 23 +fld public final static int FMUL = 106 +fld public final static int FNEG = 118 +fld public final static int FREM = 114 +fld public final static int FRETURN = 174 +fld public final static int FSTORE = 56 +fld public final static int FSUB = 102 +fld public final static int F_APPEND = 1 +fld public final static int F_CHOP = 2 +fld public final static int F_FULL = 0 +fld public final static int F_NEW = -1 +fld public final static int F_SAME = 3 +fld public final static int F_SAME1 = 4 +fld public final static int GETFIELD = 180 +fld public final static int GETSTATIC = 178 +fld public final static int GOTO = 167 +fld public final static int H_GETFIELD = 1 +fld public final static int H_GETSTATIC = 2 +fld public final static int H_INVOKEINTERFACE = 9 +fld public final static int H_INVOKESPECIAL = 7 +fld public final static int H_INVOKESTATIC = 6 +fld public final static int H_INVOKEVIRTUAL = 5 +fld public final static int H_NEWINVOKESPECIAL = 8 +fld public final static int H_PUTFIELD = 3 +fld public final static int H_PUTSTATIC = 4 +fld public final static int I2B = 145 +fld public final static int I2C = 146 +fld public final static int I2D = 135 +fld public final static int I2F = 134 +fld public final static int I2L = 133 +fld public final static int I2S = 147 +fld public final static int IADD = 96 +fld public final static int IALOAD = 46 +fld public final static int IAND = 126 +fld public final static int IASTORE = 79 +fld public final static int ICONST_0 = 3 +fld public final static int ICONST_1 = 4 +fld public final static int ICONST_2 = 5 +fld public final static int ICONST_3 = 6 +fld public final static int ICONST_4 = 7 +fld public final static int ICONST_5 = 8 +fld public final static int ICONST_M1 = 2 +fld public final static int IDIV = 108 +fld public final static int IFEQ = 153 +fld public final static int IFGE = 156 +fld public final static int IFGT = 157 +fld public final static int IFLE = 158 +fld public final static int IFLT = 155 +fld public final static int IFNE = 154 +fld public final static int IFNONNULL = 199 +fld public final static int IFNULL = 198 +fld public final static int IF_ACMPEQ = 165 +fld public final static int IF_ACMPNE = 166 +fld public final static int IF_ICMPEQ = 159 +fld public final static int IF_ICMPGE = 162 +fld public final static int IF_ICMPGT = 163 +fld public final static int IF_ICMPLE = 164 +fld public final static int IF_ICMPLT = 161 +fld public final static int IF_ICMPNE = 160 +fld public final static int IINC = 132 +fld public final static int ILOAD = 21 +fld public final static int IMUL = 104 +fld public final static int INEG = 116 +fld public final static int INSTANCEOF = 193 +fld public final static int INVOKEDYNAMIC = 186 +fld public final static int INVOKEINTERFACE = 185 +fld public final static int INVOKESPECIAL = 183 +fld public final static int INVOKESTATIC = 184 +fld public final static int INVOKEVIRTUAL = 182 +fld public final static int IOR = 128 +fld public final static int IREM = 112 +fld public final static int IRETURN = 172 +fld public final static int ISHL = 120 +fld public final static int ISHR = 122 +fld public final static int ISTORE = 54 +fld public final static int ISUB = 100 +fld public final static int IUSHR = 124 +fld public final static int IXOR = 130 +fld public final static int JSR = 168 +fld public final static int L2D = 138 +fld public final static int L2F = 137 +fld public final static int L2I = 136 +fld public final static int LADD = 97 +fld public final static int LALOAD = 47 +fld public final static int LAND = 127 +fld public final static int LASTORE = 80 +fld public final static int LCMP = 148 +fld public final static int LCONST_0 = 9 +fld public final static int LCONST_1 = 10 +fld public final static int LDC = 18 +fld public final static int LDIV = 109 +fld public final static int LLOAD = 22 +fld public final static int LMUL = 105 +fld public final static int LNEG = 117 +fld public final static int LOOKUPSWITCH = 171 +fld public final static int LOR = 129 +fld public final static int LREM = 113 +fld public final static int LRETURN = 173 +fld public final static int LSHL = 121 +fld public final static int LSHR = 123 +fld public final static int LSTORE = 55 +fld public final static int LSUB = 101 +fld public final static int LUSHR = 125 +fld public final static int LXOR = 131 +fld public final static int MONITORENTER = 194 +fld public final static int MONITOREXIT = 195 +fld public final static int MULTIANEWARRAY = 197 +fld public final static int NEW = 187 +fld public final static int NEWARRAY = 188 +fld public final static int NOP = 0 +fld public final static int POP = 87 +fld public final static int POP2 = 88 +fld public final static int PUTFIELD = 181 +fld public final static int PUTSTATIC = 179 +fld public final static int RET = 169 +fld public final static int RETURN = 177 +fld public final static int SALOAD = 53 +fld public final static int SASTORE = 86 +fld public final static int SIPUSH = 17 +fld public final static int SWAP = 95 +fld public final static int TABLESWITCH = 170 +fld public final static int T_BOOLEAN = 4 +fld public final static int T_BYTE = 8 +fld public final static int T_CHAR = 5 +fld public final static int T_DOUBLE = 7 +fld public final static int T_FLOAT = 6 +fld public final static int T_INT = 10 +fld public final static int T_LONG = 11 +fld public final static int T_SHORT = 9 +fld public final static int V1_1 = 196653 +fld public final static int V1_2 = 46 +fld public final static int V1_3 = 47 +fld public final static int V1_4 = 48 +fld public final static int V1_5 = 49 +fld public final static int V1_6 = 50 +fld public final static int V1_7 = 51 +fld public final static int V1_8 = 52 +fld public final static java.lang.Integer DOUBLE +fld public final static java.lang.Integer FLOAT +fld public final static java.lang.Integer INTEGER +fld public final static java.lang.Integer LONG +fld public final static java.lang.Integer NULL +fld public final static java.lang.Integer TOP +fld public final static java.lang.Integer UNINITIALIZED_THIS + +CLSS public org.objectweb.asm.tree.analysis.Analyzer +cons public init(org.objectweb.asm.tree.analysis.Interpreter) +intf org.objectweb.asm.Opcodes +meth protected boolean newControlFlowExceptionEdge(int,int) +meth protected boolean newControlFlowExceptionEdge(int,org.objectweb.asm.tree.TryCatchBlockNode) +meth protected org.objectweb.asm.tree.analysis.Frame newFrame(int,int) +meth protected org.objectweb.asm.tree.analysis.Frame newFrame(org.objectweb.asm.tree.analysis.Frame) +meth protected void init(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth protected void newControlFlowEdge(int,int) +meth public java.util.List getHandlers(int) +meth public org.objectweb.asm.tree.analysis.Frame[] analyze(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Frame[] getFrames() +supr java.lang.Object +hfds frames,handlers,insns,interpreter,n,queue,queued,subroutines,top + +CLSS public org.objectweb.asm.tree.analysis.AnalyzerException +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Object,org.objectweb.asm.tree.analysis.Value) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Throwable) +fld public final org.objectweb.asm.tree.AbstractInsnNode node +supr java.lang.Exception + +CLSS public org.objectweb.asm.tree.analysis.BasicInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.BasicValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.BasicValue +cons public init(org.objectweb.asm.Type) +fld public final static org.objectweb.asm.tree.analysis.BasicValue DOUBLE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue FLOAT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue INT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue LONG_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue REFERENCE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue RETURNADDRESS_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue UNINITIALIZED_VALUE +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public boolean isReference() +meth public int getSize() +meth public int hashCode() +meth public java.lang.String toString() +meth public org.objectweb.asm.Type getType() +supr java.lang.Object +hfds type + +CLSS public org.objectweb.asm.tree.analysis.BasicVerifier +cons protected init(int) +cons public init() +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.BasicInterpreter + +CLSS public org.objectweb.asm.tree.analysis.Frame +cons public init(int,int) +cons public init(org.objectweb.asm.tree.analysis.Frame) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,boolean[]) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,org.objectweb.asm.tree.analysis.Interpreter) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public int getLocals() +meth public int getMaxStackSize() +meth public int getStackSize() +meth public java.lang.String toString() +meth public org.objectweb.asm.tree.analysis.Frame init(org.objectweb.asm.tree.analysis.Frame) +meth public org.objectweb.asm.tree.analysis.Value getLocal(int) +meth public org.objectweb.asm.tree.analysis.Value getStack(int) +meth public org.objectweb.asm.tree.analysis.Value pop() +meth public void clearStack() +meth public void execute(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Interpreter) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void push(org.objectweb.asm.tree.analysis.Value) +meth public void setLocal(int,org.objectweb.asm.tree.analysis.Value) +meth public void setReturn(org.objectweb.asm.tree.analysis.Value) +supr java.lang.Object +hfds locals,returnValue,top,values + +CLSS public abstract org.objectweb.asm.tree.analysis.Interpreter +cons protected init(int) +fld protected final int api +meth public abstract org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public abstract org.objectweb.asm.tree.analysis.Value naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value newValue(org.objectweb.asm.Type) +meth public abstract org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr java.lang.Object + +CLSS public org.objectweb.asm.tree.analysis.SimpleVerifier +cons protected init(int,org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +cons public init() +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,boolean) +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isAssignableFrom(org.objectweb.asm.Type,org.objectweb.asm.Type) +meth protected boolean isInterface(org.objectweb.asm.Type) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected java.lang.Class getClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.Type getSuperClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public void setClassLoader(java.lang.ClassLoader) +supr org.objectweb.asm.tree.analysis.BasicVerifier +hfds class$java$lang$Object,currentClass,currentClassInterfaces,currentSuperClass,isInterface,loader + +CLSS public org.objectweb.asm.tree.analysis.SourceInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.SourceValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue merge(org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) +meth public org.objectweb.asm.tree.analysis.SourceValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) +meth public org.objectweb.asm.tree.analysis.SourceValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.SourceValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.Value binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value merge(org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) +meth public org.objectweb.asm.tree.analysis.Value ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Value unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Value,org.objectweb.asm.tree.analysis.Value) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.SourceValue +cons public init(int) +cons public init(int,java.util.Set) +cons public init(int,org.objectweb.asm.tree.AbstractInsnNode) +fld public final int size +fld public final java.util.Set insns +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public int getSize() +meth public int hashCode() +supr java.lang.Object + +CLSS public abstract interface org.objectweb.asm.tree.analysis.Value +meth public abstract int getSize() + diff --git a/asm-analysis/src/test/resources/sigtest-6.0.txt b/asm-analysis/src/test/resources/sigtest-6.0.txt new file mode 100644 index 000000000..b05d037d8 --- /dev/null +++ b/asm-analysis/src/test/resources/sigtest-6.0.txt @@ -0,0 +1,430 @@ +#Signature file v4.1 +#Version 6.0 + +CLSS public abstract interface java.io.Serializable + +CLSS public java.lang.Exception +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +supr java.lang.Throwable +hfds serialVersionUID + +CLSS public java.lang.Object +cons public init() +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException +meth protected void finalize() throws java.lang.Throwable +meth public boolean equals(java.lang.Object) +meth public final java.lang.Class getClass() +meth public final void notify() +meth public final void notifyAll() +meth public final void wait() throws java.lang.InterruptedException +meth public final void wait(long) throws java.lang.InterruptedException +meth public final void wait(long,int) throws java.lang.InterruptedException +meth public int hashCode() +meth public java.lang.String toString() + +CLSS public java.lang.Throwable +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +intf java.io.Serializable +meth public final java.lang.Throwable[] getSuppressed() +meth public final void addSuppressed(java.lang.Throwable) +meth public java.lang.StackTraceElement[] getStackTrace() +meth public java.lang.String getLocalizedMessage() +meth public java.lang.String getMessage() +meth public java.lang.String toString() +meth public java.lang.Throwable fillInStackTrace() +meth public java.lang.Throwable getCause() +meth public java.lang.Throwable initCause(java.lang.Throwable) +meth public void printStackTrace() +meth public void printStackTrace(java.io.PrintStream) +meth public void printStackTrace(java.io.PrintWriter) +meth public void setStackTrace(java.lang.StackTraceElement[]) +supr java.lang.Object +hfds CAUSE_CAPTION,EMPTY_THROWABLE_ARRAY,NULL_CAUSE_MESSAGE,SELF_SUPPRESSION_MESSAGE,SUPPRESSED_CAPTION,SUPPRESSED_SENTINEL,UNASSIGNED_STACK,backtrace,cause,detailMessage,serialVersionUID,stackTrace,suppressedExceptions +hcls PrintStreamOrWriter,SentinelHolder,WrappedPrintStream,WrappedPrintWriter + +CLSS public abstract interface org.objectweb.asm.Opcodes +fld public final static int AALOAD = 50 +fld public final static int AASTORE = 83 +fld public final static int ACC_ABSTRACT = 1024 +fld public final static int ACC_ANNOTATION = 8192 +fld public final static int ACC_BRIDGE = 64 +fld public final static int ACC_DEPRECATED = 131072 +fld public final static int ACC_ENUM = 16384 +fld public final static int ACC_FINAL = 16 +fld public final static int ACC_INTERFACE = 512 +fld public final static int ACC_MANDATED = 32768 +fld public final static int ACC_MODULE = 32768 +fld public final static int ACC_NATIVE = 256 +fld public final static int ACC_OPEN = 32 +fld public final static int ACC_PRIVATE = 2 +fld public final static int ACC_PROTECTED = 4 +fld public final static int ACC_PUBLIC = 1 +fld public final static int ACC_STATIC = 8 +fld public final static int ACC_STATIC_PHASE = 64 +fld public final static int ACC_STRICT = 2048 +fld public final static int ACC_SUPER = 32 +fld public final static int ACC_SYNCHRONIZED = 32 +fld public final static int ACC_SYNTHETIC = 4096 +fld public final static int ACC_TRANSIENT = 128 +fld public final static int ACC_TRANSITIVE = 32 +fld public final static int ACC_VARARGS = 128 +fld public final static int ACC_VOLATILE = 64 +fld public final static int ACONST_NULL = 1 +fld public final static int ALOAD = 25 +fld public final static int ANEWARRAY = 189 +fld public final static int ARETURN = 176 +fld public final static int ARRAYLENGTH = 190 +fld public final static int ASM4 = 262144 +fld public final static int ASM5 = 327680 +fld public final static int ASM6 = 393216 +fld public final static int ASTORE = 58 +fld public final static int ATHROW = 191 +fld public final static int BALOAD = 51 +fld public final static int BASTORE = 84 +fld public final static int BIPUSH = 16 +fld public final static int CALOAD = 52 +fld public final static int CASTORE = 85 +fld public final static int CHECKCAST = 192 +fld public final static int D2F = 144 +fld public final static int D2I = 142 +fld public final static int D2L = 143 +fld public final static int DADD = 99 +fld public final static int DALOAD = 49 +fld public final static int DASTORE = 82 +fld public final static int DCMPG = 152 +fld public final static int DCMPL = 151 +fld public final static int DCONST_0 = 14 +fld public final static int DCONST_1 = 15 +fld public final static int DDIV = 111 +fld public final static int DLOAD = 24 +fld public final static int DMUL = 107 +fld public final static int DNEG = 119 +fld public final static int DREM = 115 +fld public final static int DRETURN = 175 +fld public final static int DSTORE = 57 +fld public final static int DSUB = 103 +fld public final static int DUP = 89 +fld public final static int DUP2 = 92 +fld public final static int DUP2_X1 = 93 +fld public final static int DUP2_X2 = 94 +fld public final static int DUP_X1 = 90 +fld public final static int DUP_X2 = 91 +fld public final static int F2D = 141 +fld public final static int F2I = 139 +fld public final static int F2L = 140 +fld public final static int FADD = 98 +fld public final static int FALOAD = 48 +fld public final static int FASTORE = 81 +fld public final static int FCMPG = 150 +fld public final static int FCMPL = 149 +fld public final static int FCONST_0 = 11 +fld public final static int FCONST_1 = 12 +fld public final static int FCONST_2 = 13 +fld public final static int FDIV = 110 +fld public final static int FLOAD = 23 +fld public final static int FMUL = 106 +fld public final static int FNEG = 118 +fld public final static int FREM = 114 +fld public final static int FRETURN = 174 +fld public final static int FSTORE = 56 +fld public final static int FSUB = 102 +fld public final static int F_APPEND = 1 +fld public final static int F_CHOP = 2 +fld public final static int F_FULL = 0 +fld public final static int F_NEW = -1 +fld public final static int F_SAME = 3 +fld public final static int F_SAME1 = 4 +fld public final static int GETFIELD = 180 +fld public final static int GETSTATIC = 178 +fld public final static int GOTO = 167 +fld public final static int H_GETFIELD = 1 +fld public final static int H_GETSTATIC = 2 +fld public final static int H_INVOKEINTERFACE = 9 +fld public final static int H_INVOKESPECIAL = 7 +fld public final static int H_INVOKESTATIC = 6 +fld public final static int H_INVOKEVIRTUAL = 5 +fld public final static int H_NEWINVOKESPECIAL = 8 +fld public final static int H_PUTFIELD = 3 +fld public final static int H_PUTSTATIC = 4 +fld public final static int I2B = 145 +fld public final static int I2C = 146 +fld public final static int I2D = 135 +fld public final static int I2F = 134 +fld public final static int I2L = 133 +fld public final static int I2S = 147 +fld public final static int IADD = 96 +fld public final static int IALOAD = 46 +fld public final static int IAND = 126 +fld public final static int IASTORE = 79 +fld public final static int ICONST_0 = 3 +fld public final static int ICONST_1 = 4 +fld public final static int ICONST_2 = 5 +fld public final static int ICONST_3 = 6 +fld public final static int ICONST_4 = 7 +fld public final static int ICONST_5 = 8 +fld public final static int ICONST_M1 = 2 +fld public final static int IDIV = 108 +fld public final static int IFEQ = 153 +fld public final static int IFGE = 156 +fld public final static int IFGT = 157 +fld public final static int IFLE = 158 +fld public final static int IFLT = 155 +fld public final static int IFNE = 154 +fld public final static int IFNONNULL = 199 +fld public final static int IFNULL = 198 +fld public final static int IF_ACMPEQ = 165 +fld public final static int IF_ACMPNE = 166 +fld public final static int IF_ICMPEQ = 159 +fld public final static int IF_ICMPGE = 162 +fld public final static int IF_ICMPGT = 163 +fld public final static int IF_ICMPLE = 164 +fld public final static int IF_ICMPLT = 161 +fld public final static int IF_ICMPNE = 160 +fld public final static int IINC = 132 +fld public final static int ILOAD = 21 +fld public final static int IMUL = 104 +fld public final static int INEG = 116 +fld public final static int INSTANCEOF = 193 +fld public final static int INVOKEDYNAMIC = 186 +fld public final static int INVOKEINTERFACE = 185 +fld public final static int INVOKESPECIAL = 183 +fld public final static int INVOKESTATIC = 184 +fld public final static int INVOKEVIRTUAL = 182 +fld public final static int IOR = 128 +fld public final static int IREM = 112 +fld public final static int IRETURN = 172 +fld public final static int ISHL = 120 +fld public final static int ISHR = 122 +fld public final static int ISTORE = 54 +fld public final static int ISUB = 100 +fld public final static int IUSHR = 124 +fld public final static int IXOR = 130 +fld public final static int JSR = 168 +fld public final static int L2D = 138 +fld public final static int L2F = 137 +fld public final static int L2I = 136 +fld public final static int LADD = 97 +fld public final static int LALOAD = 47 +fld public final static int LAND = 127 +fld public final static int LASTORE = 80 +fld public final static int LCMP = 148 +fld public final static int LCONST_0 = 9 +fld public final static int LCONST_1 = 10 +fld public final static int LDC = 18 +fld public final static int LDIV = 109 +fld public final static int LLOAD = 22 +fld public final static int LMUL = 105 +fld public final static int LNEG = 117 +fld public final static int LOOKUPSWITCH = 171 +fld public final static int LOR = 129 +fld public final static int LREM = 113 +fld public final static int LRETURN = 173 +fld public final static int LSHL = 121 +fld public final static int LSHR = 123 +fld public final static int LSTORE = 55 +fld public final static int LSUB = 101 +fld public final static int LUSHR = 125 +fld public final static int LXOR = 131 +fld public final static int MONITORENTER = 194 +fld public final static int MONITOREXIT = 195 +fld public final static int MULTIANEWARRAY = 197 +fld public final static int NEW = 187 +fld public final static int NEWARRAY = 188 +fld public final static int NOP = 0 +fld public final static int POP = 87 +fld public final static int POP2 = 88 +fld public final static int PUTFIELD = 181 +fld public final static int PUTSTATIC = 179 +fld public final static int RET = 169 +fld public final static int RETURN = 177 +fld public final static int SALOAD = 53 +fld public final static int SASTORE = 86 +fld public final static int SIPUSH = 17 +fld public final static int SWAP = 95 +fld public final static int TABLESWITCH = 170 +fld public final static int T_BOOLEAN = 4 +fld public final static int T_BYTE = 8 +fld public final static int T_CHAR = 5 +fld public final static int T_DOUBLE = 7 +fld public final static int T_FLOAT = 6 +fld public final static int T_INT = 10 +fld public final static int T_LONG = 11 +fld public final static int T_SHORT = 9 +fld public final static int V1_1 = 196653 +fld public final static int V1_2 = 46 +fld public final static int V1_3 = 47 +fld public final static int V1_4 = 48 +fld public final static int V1_5 = 49 +fld public final static int V1_6 = 50 +fld public final static int V1_7 = 51 +fld public final static int V1_8 = 52 +fld public final static int V9 = 53 +fld public final static java.lang.Integer DOUBLE +fld public final static java.lang.Integer FLOAT +fld public final static java.lang.Integer INTEGER +fld public final static java.lang.Integer LONG +fld public final static java.lang.Integer NULL +fld public final static java.lang.Integer TOP +fld public final static java.lang.Integer UNINITIALIZED_THIS + +CLSS public org.objectweb.asm.tree.analysis.Analyzer<%0 extends org.objectweb.asm.tree.analysis.Value> +cons public init(org.objectweb.asm.tree.analysis.Interpreter<{org.objectweb.asm.tree.analysis.Analyzer%0}>) +intf org.objectweb.asm.Opcodes +meth protected boolean newControlFlowExceptionEdge(int,int) +meth protected boolean newControlFlowExceptionEdge(int,org.objectweb.asm.tree.TryCatchBlockNode) +meth protected org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}> newFrame(int,int) +meth protected org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}> newFrame(org.objectweb.asm.tree.analysis.Frame) +meth protected void init(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth protected void newControlFlowEdge(int,int) +meth public java.util.List getHandlers(int) +meth public org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}>[] analyze(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}>[] getFrames() +supr java.lang.Object +hfds frames,handlers,insns,interpreter,n,queue,queued,subroutines,top + +CLSS public org.objectweb.asm.tree.analysis.AnalyzerException +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Object,org.objectweb.asm.tree.analysis.Value) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Throwable) +fld public final org.objectweb.asm.tree.AbstractInsnNode node +supr java.lang.Exception + +CLSS public org.objectweb.asm.tree.analysis.BasicInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.BasicValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.BasicValue +cons public init(org.objectweb.asm.Type) +fld public final static org.objectweb.asm.tree.analysis.BasicValue DOUBLE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue FLOAT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue INT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue LONG_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue REFERENCE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue RETURNADDRESS_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue UNINITIALIZED_VALUE +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public boolean isReference() +meth public int getSize() +meth public int hashCode() +meth public java.lang.String toString() +meth public org.objectweb.asm.Type getType() +supr java.lang.Object +hfds type + +CLSS public org.objectweb.asm.tree.analysis.BasicVerifier +cons protected init(int) +cons public init() +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.BasicInterpreter + +CLSS public org.objectweb.asm.tree.analysis.Frame<%0 extends org.objectweb.asm.tree.analysis.Value> +cons public init(int,int) +cons public init(org.objectweb.asm.tree.analysis.Frame) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,boolean[]) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,org.objectweb.asm.tree.analysis.Interpreter<{org.objectweb.asm.tree.analysis.Frame%0}>) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public int getLocals() +meth public int getMaxStackSize() +meth public int getStackSize() +meth public java.lang.String toString() +meth public org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Frame%0}> init(org.objectweb.asm.tree.analysis.Frame) +meth public void clearStack() +meth public void execute(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Interpreter<{org.objectweb.asm.tree.analysis.Frame%0}>) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void push({org.objectweb.asm.tree.analysis.Frame%0}) +meth public void setLocal(int,{org.objectweb.asm.tree.analysis.Frame%0}) +meth public void setReturn({org.objectweb.asm.tree.analysis.Frame%0}) +meth public {org.objectweb.asm.tree.analysis.Frame%0} getLocal(int) +meth public {org.objectweb.asm.tree.analysis.Frame%0} getStack(int) +meth public {org.objectweb.asm.tree.analysis.Frame%0} pop() +supr java.lang.Object +hfds locals,returnValue,top,values + +CLSS public abstract org.objectweb.asm.tree.analysis.Interpreter<%0 extends org.objectweb.asm.tree.analysis.Value> +cons protected init(int) +fld protected final int api +meth public abstract void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} copyOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} merge({org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} newValue(org.objectweb.asm.Type) +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr java.lang.Object + +CLSS public org.objectweb.asm.tree.analysis.SimpleVerifier +cons protected init(int,org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +cons public init() +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,boolean) +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isAssignableFrom(org.objectweb.asm.Type,org.objectweb.asm.Type) +meth protected boolean isInterface(org.objectweb.asm.Type) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected java.lang.Class getClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.Type getSuperClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.BasicValue newValue(org.objectweb.asm.Type) +meth public void setClassLoader(java.lang.ClassLoader) +supr org.objectweb.asm.tree.analysis.BasicVerifier +hfds currentClass,currentClassInterfaces,currentSuperClass,isInterface,loader + +CLSS public org.objectweb.asm.tree.analysis.SourceInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.SourceValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue merge(org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) +meth public org.objectweb.asm.tree.analysis.SourceValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) +meth public org.objectweb.asm.tree.analysis.SourceValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.SourceValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.SourceValue +cons public init(int) +cons public init(int,java.util.Set) +cons public init(int,org.objectweb.asm.tree.AbstractInsnNode) +fld public final int size +fld public final java.util.Set insns +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public int getSize() +meth public int hashCode() +supr java.lang.Object + +CLSS public abstract interface org.objectweb.asm.tree.analysis.Value +meth public abstract int getSize() + diff --git a/asm-analysis/src/test/resources/sigtest-6.1.txt b/asm-analysis/src/test/resources/sigtest-6.1.txt new file mode 100644 index 000000000..708618e34 --- /dev/null +++ b/asm-analysis/src/test/resources/sigtest-6.1.txt @@ -0,0 +1,433 @@ +#Signature file v4.1 +#Version 6.1 + +CLSS public abstract interface java.io.Serializable + +CLSS public java.lang.Exception +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +supr java.lang.Throwable +hfds serialVersionUID + +CLSS public java.lang.Object +cons public init() +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException +meth protected void finalize() throws java.lang.Throwable +meth public boolean equals(java.lang.Object) +meth public final java.lang.Class getClass() +meth public final void notify() +meth public final void notifyAll() +meth public final void wait() throws java.lang.InterruptedException +meth public final void wait(long) throws java.lang.InterruptedException +meth public final void wait(long,int) throws java.lang.InterruptedException +meth public int hashCode() +meth public java.lang.String toString() + +CLSS public java.lang.Throwable +cons protected init(java.lang.String,java.lang.Throwable,boolean,boolean) +cons public init() +cons public init(java.lang.String) +cons public init(java.lang.String,java.lang.Throwable) +cons public init(java.lang.Throwable) +intf java.io.Serializable +meth public final java.lang.Throwable[] getSuppressed() +meth public final void addSuppressed(java.lang.Throwable) +meth public java.lang.StackTraceElement[] getStackTrace() +meth public java.lang.String getLocalizedMessage() +meth public java.lang.String getMessage() +meth public java.lang.String toString() +meth public java.lang.Throwable fillInStackTrace() +meth public java.lang.Throwable getCause() +meth public java.lang.Throwable initCause(java.lang.Throwable) +meth public void printStackTrace() +meth public void printStackTrace(java.io.PrintStream) +meth public void printStackTrace(java.io.PrintWriter) +meth public void setStackTrace(java.lang.StackTraceElement[]) +supr java.lang.Object +hfds CAUSE_CAPTION,EMPTY_THROWABLE_ARRAY,NULL_CAUSE_MESSAGE,SELF_SUPPRESSION_MESSAGE,SUPPRESSED_CAPTION,SUPPRESSED_SENTINEL,UNASSIGNED_STACK,backtrace,cause,detailMessage,serialVersionUID,stackTrace,suppressedExceptions +hcls PrintStreamOrWriter,SentinelHolder,WrappedPrintStream,WrappedPrintWriter + +CLSS public abstract interface org.objectweb.asm.Opcodes +fld public final static int AALOAD = 50 +fld public final static int AASTORE = 83 +fld public final static int ACC_ABSTRACT = 1024 +fld public final static int ACC_ANNOTATION = 8192 +fld public final static int ACC_BRIDGE = 64 +fld public final static int ACC_DEPRECATED = 131072 +fld public final static int ACC_ENUM = 16384 +fld public final static int ACC_FINAL = 16 +fld public final static int ACC_INTERFACE = 512 +fld public final static int ACC_MANDATED = 32768 +fld public final static int ACC_MODULE = 32768 +fld public final static int ACC_NATIVE = 256 +fld public final static int ACC_OPEN = 32 +fld public final static int ACC_PRIVATE = 2 +fld public final static int ACC_PROTECTED = 4 +fld public final static int ACC_PUBLIC = 1 +fld public final static int ACC_STATIC = 8 +fld public final static int ACC_STATIC_PHASE = 64 +fld public final static int ACC_STRICT = 2048 +fld public final static int ACC_SUPER = 32 +fld public final static int ACC_SYNCHRONIZED = 32 +fld public final static int ACC_SYNTHETIC = 4096 +fld public final static int ACC_TRANSIENT = 128 +fld public final static int ACC_TRANSITIVE = 32 +fld public final static int ACC_VARARGS = 128 +fld public final static int ACC_VOLATILE = 64 +fld public final static int ACONST_NULL = 1 +fld public final static int ALOAD = 25 +fld public final static int ANEWARRAY = 189 +fld public final static int ARETURN = 176 +fld public final static int ARRAYLENGTH = 190 +fld public final static int ASM4 = 262144 +fld public final static int ASM5 = 327680 +fld public final static int ASM6 = 393216 +fld public final static int ASTORE = 58 +fld public final static int ATHROW = 191 +fld public final static int BALOAD = 51 +fld public final static int BASTORE = 84 +fld public final static int BIPUSH = 16 +fld public final static int CALOAD = 52 +fld public final static int CASTORE = 85 +fld public final static int CHECKCAST = 192 +fld public final static int D2F = 144 +fld public final static int D2I = 142 +fld public final static int D2L = 143 +fld public final static int DADD = 99 +fld public final static int DALOAD = 49 +fld public final static int DASTORE = 82 +fld public final static int DCMPG = 152 +fld public final static int DCMPL = 151 +fld public final static int DCONST_0 = 14 +fld public final static int DCONST_1 = 15 +fld public final static int DDIV = 111 +fld public final static int DLOAD = 24 +fld public final static int DMUL = 107 +fld public final static int DNEG = 119 +fld public final static int DREM = 115 +fld public final static int DRETURN = 175 +fld public final static int DSTORE = 57 +fld public final static int DSUB = 103 +fld public final static int DUP = 89 +fld public final static int DUP2 = 92 +fld public final static int DUP2_X1 = 93 +fld public final static int DUP2_X2 = 94 +fld public final static int DUP_X1 = 90 +fld public final static int DUP_X2 = 91 +fld public final static int F2D = 141 +fld public final static int F2I = 139 +fld public final static int F2L = 140 +fld public final static int FADD = 98 +fld public final static int FALOAD = 48 +fld public final static int FASTORE = 81 +fld public final static int FCMPG = 150 +fld public final static int FCMPL = 149 +fld public final static int FCONST_0 = 11 +fld public final static int FCONST_1 = 12 +fld public final static int FCONST_2 = 13 +fld public final static int FDIV = 110 +fld public final static int FLOAD = 23 +fld public final static int FMUL = 106 +fld public final static int FNEG = 118 +fld public final static int FREM = 114 +fld public final static int FRETURN = 174 +fld public final static int FSTORE = 56 +fld public final static int FSUB = 102 +fld public final static int F_APPEND = 1 +fld public final static int F_CHOP = 2 +fld public final static int F_FULL = 0 +fld public final static int F_NEW = -1 +fld public final static int F_SAME = 3 +fld public final static int F_SAME1 = 4 +fld public final static int GETFIELD = 180 +fld public final static int GETSTATIC = 178 +fld public final static int GOTO = 167 +fld public final static int H_GETFIELD = 1 +fld public final static int H_GETSTATIC = 2 +fld public final static int H_INVOKEINTERFACE = 9 +fld public final static int H_INVOKESPECIAL = 7 +fld public final static int H_INVOKESTATIC = 6 +fld public final static int H_INVOKEVIRTUAL = 5 +fld public final static int H_NEWINVOKESPECIAL = 8 +fld public final static int H_PUTFIELD = 3 +fld public final static int H_PUTSTATIC = 4 +fld public final static int I2B = 145 +fld public final static int I2C = 146 +fld public final static int I2D = 135 +fld public final static int I2F = 134 +fld public final static int I2L = 133 +fld public final static int I2S = 147 +fld public final static int IADD = 96 +fld public final static int IALOAD = 46 +fld public final static int IAND = 126 +fld public final static int IASTORE = 79 +fld public final static int ICONST_0 = 3 +fld public final static int ICONST_1 = 4 +fld public final static int ICONST_2 = 5 +fld public final static int ICONST_3 = 6 +fld public final static int ICONST_4 = 7 +fld public final static int ICONST_5 = 8 +fld public final static int ICONST_M1 = 2 +fld public final static int IDIV = 108 +fld public final static int IFEQ = 153 +fld public final static int IFGE = 156 +fld public final static int IFGT = 157 +fld public final static int IFLE = 158 +fld public final static int IFLT = 155 +fld public final static int IFNE = 154 +fld public final static int IFNONNULL = 199 +fld public final static int IFNULL = 198 +fld public final static int IF_ACMPEQ = 165 +fld public final static int IF_ACMPNE = 166 +fld public final static int IF_ICMPEQ = 159 +fld public final static int IF_ICMPGE = 162 +fld public final static int IF_ICMPGT = 163 +fld public final static int IF_ICMPLE = 164 +fld public final static int IF_ICMPLT = 161 +fld public final static int IF_ICMPNE = 160 +fld public final static int IINC = 132 +fld public final static int ILOAD = 21 +fld public final static int IMUL = 104 +fld public final static int INEG = 116 +fld public final static int INSTANCEOF = 193 +fld public final static int INVOKEDYNAMIC = 186 +fld public final static int INVOKEINTERFACE = 185 +fld public final static int INVOKESPECIAL = 183 +fld public final static int INVOKESTATIC = 184 +fld public final static int INVOKEVIRTUAL = 182 +fld public final static int IOR = 128 +fld public final static int IREM = 112 +fld public final static int IRETURN = 172 +fld public final static int ISHL = 120 +fld public final static int ISHR = 122 +fld public final static int ISTORE = 54 +fld public final static int ISUB = 100 +fld public final static int IUSHR = 124 +fld public final static int IXOR = 130 +fld public final static int JSR = 168 +fld public final static int L2D = 138 +fld public final static int L2F = 137 +fld public final static int L2I = 136 +fld public final static int LADD = 97 +fld public final static int LALOAD = 47 +fld public final static int LAND = 127 +fld public final static int LASTORE = 80 +fld public final static int LCMP = 148 +fld public final static int LCONST_0 = 9 +fld public final static int LCONST_1 = 10 +fld public final static int LDC = 18 +fld public final static int LDIV = 109 +fld public final static int LLOAD = 22 +fld public final static int LMUL = 105 +fld public final static int LNEG = 117 +fld public final static int LOOKUPSWITCH = 171 +fld public final static int LOR = 129 +fld public final static int LREM = 113 +fld public final static int LRETURN = 173 +fld public final static int LSHL = 121 +fld public final static int LSHR = 123 +fld public final static int LSTORE = 55 +fld public final static int LSUB = 101 +fld public final static int LUSHR = 125 +fld public final static int LXOR = 131 +fld public final static int MONITORENTER = 194 +fld public final static int MONITOREXIT = 195 +fld public final static int MULTIANEWARRAY = 197 +fld public final static int NEW = 187 +fld public final static int NEWARRAY = 188 +fld public final static int NOP = 0 +fld public final static int POP = 87 +fld public final static int POP2 = 88 +fld public final static int PUTFIELD = 181 +fld public final static int PUTSTATIC = 179 +fld public final static int RET = 169 +fld public final static int RETURN = 177 +fld public final static int SALOAD = 53 +fld public final static int SASTORE = 86 +fld public final static int SIPUSH = 17 +fld public final static int SWAP = 95 +fld public final static int TABLESWITCH = 170 +fld public final static int T_BOOLEAN = 4 +fld public final static int T_BYTE = 8 +fld public final static int T_CHAR = 5 +fld public final static int T_DOUBLE = 7 +fld public final static int T_FLOAT = 6 +fld public final static int T_INT = 10 +fld public final static int T_LONG = 11 +fld public final static int T_SHORT = 9 +fld public final static int V10 = 54 +fld public final static int V1_1 = 196653 +fld public final static int V1_2 = 46 +fld public final static int V1_3 = 47 +fld public final static int V1_4 = 48 +fld public final static int V1_5 = 49 +fld public final static int V1_6 = 50 +fld public final static int V1_7 = 51 +fld public final static int V1_8 = 52 +fld public final static int V9 = 53 +fld public final static java.lang.Integer DOUBLE +fld public final static java.lang.Integer FLOAT +fld public final static java.lang.Integer INTEGER +fld public final static java.lang.Integer LONG +fld public final static java.lang.Integer NULL +fld public final static java.lang.Integer TOP +fld public final static java.lang.Integer UNINITIALIZED_THIS + +CLSS public org.objectweb.asm.tree.analysis.Analyzer<%0 extends org.objectweb.asm.tree.analysis.Value> +cons public init(org.objectweb.asm.tree.analysis.Interpreter<{org.objectweb.asm.tree.analysis.Analyzer%0}>) +intf org.objectweb.asm.Opcodes +meth protected boolean newControlFlowExceptionEdge(int,int) +meth protected boolean newControlFlowExceptionEdge(int,org.objectweb.asm.tree.TryCatchBlockNode) +meth protected org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}> newFrame(int,int) +meth protected org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}> newFrame(org.objectweb.asm.tree.analysis.Frame) +meth protected void init(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth protected void newControlFlowEdge(int,int) +meth public java.util.List getHandlers(int) +meth public org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}>[] analyze(java.lang.String,org.objectweb.asm.tree.MethodNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Analyzer%0}>[] getFrames() +supr java.lang.Object +hfds frames,handlers,inInstructionsToProcess,insnList,insnListSize,instructionsToProcess,interpreter,numInstructionsToProcess,subroutines + +CLSS public org.objectweb.asm.tree.analysis.AnalyzerException +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Object,org.objectweb.asm.tree.analysis.Value) +cons public init(org.objectweb.asm.tree.AbstractInsnNode,java.lang.String,java.lang.Throwable) +fld public final org.objectweb.asm.tree.AbstractInsnNode node +supr java.lang.Exception +hfds serialVersionUID + +CLSS public org.objectweb.asm.tree.analysis.BasicInterpreter +cons protected init(int) +cons public init() +fld public final static org.objectweb.asm.Type NULL_TYPE +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.BasicValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.BasicValue +cons public init(org.objectweb.asm.Type) +fld public final static org.objectweb.asm.tree.analysis.BasicValue DOUBLE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue FLOAT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue INT_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue LONG_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue REFERENCE_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue RETURNADDRESS_VALUE +fld public final static org.objectweb.asm.tree.analysis.BasicValue UNINITIALIZED_VALUE +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public boolean isReference() +meth public int getSize() +meth public int hashCode() +meth public java.lang.String toString() +meth public org.objectweb.asm.Type getType() +supr java.lang.Object +hfds type + +CLSS public org.objectweb.asm.tree.analysis.BasicVerifier +cons protected init(int) +cons public init() +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr org.objectweb.asm.tree.analysis.BasicInterpreter + +CLSS public org.objectweb.asm.tree.analysis.Frame<%0 extends org.objectweb.asm.tree.analysis.Value> +cons public init(int,int) +cons public init(org.objectweb.asm.tree.analysis.Frame) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,boolean[]) +meth public boolean merge(org.objectweb.asm.tree.analysis.Frame,org.objectweb.asm.tree.analysis.Interpreter<{org.objectweb.asm.tree.analysis.Frame%0}>) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public int getLocals() +meth public int getMaxStackSize() +meth public int getStackSize() +meth public java.lang.String toString() +meth public org.objectweb.asm.tree.analysis.Frame<{org.objectweb.asm.tree.analysis.Frame%0}> init(org.objectweb.asm.tree.analysis.Frame) +meth public void clearStack() +meth public void execute(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.Interpreter<{org.objectweb.asm.tree.analysis.Frame%0}>) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public void push({org.objectweb.asm.tree.analysis.Frame%0}) +meth public void setLocal(int,{org.objectweb.asm.tree.analysis.Frame%0}) +meth public void setReturn({org.objectweb.asm.tree.analysis.Frame%0}) +meth public {org.objectweb.asm.tree.analysis.Frame%0} getLocal(int) +meth public {org.objectweb.asm.tree.analysis.Frame%0} getStack(int) +meth public {org.objectweb.asm.tree.analysis.Frame%0} pop() +supr java.lang.Object +hfds nLocals,nStack,returnValue,values + +CLSS public abstract org.objectweb.asm.tree.analysis.Interpreter<%0 extends org.objectweb.asm.tree.analysis.Value> +cons protected init(int) +fld protected final int api +meth public abstract void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} copyOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} merge({org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} newOperation(org.objectweb.asm.tree.AbstractInsnNode) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} newValue(org.objectweb.asm.Type) +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0},{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public abstract {org.objectweb.asm.tree.analysis.Interpreter%0} unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,{org.objectweb.asm.tree.analysis.Interpreter%0}) throws org.objectweb.asm.tree.analysis.AnalyzerException +supr java.lang.Object + +CLSS public org.objectweb.asm.tree.analysis.SimpleVerifier +cons protected init(int,org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +cons public init() +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,boolean) +cons public init(org.objectweb.asm.Type,org.objectweb.asm.Type,java.util.List,boolean) +meth protected boolean isArrayValue(org.objectweb.asm.tree.analysis.BasicValue) +meth protected boolean isAssignableFrom(org.objectweb.asm.Type,org.objectweb.asm.Type) +meth protected boolean isInterface(org.objectweb.asm.Type) +meth protected boolean isSubTypeOf(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth protected java.lang.Class getClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.Type getSuperClass(org.objectweb.asm.Type) +meth protected org.objectweb.asm.tree.analysis.BasicValue getElementValue(org.objectweb.asm.tree.analysis.BasicValue) throws org.objectweb.asm.tree.analysis.AnalyzerException +meth public org.objectweb.asm.tree.analysis.BasicValue merge(org.objectweb.asm.tree.analysis.BasicValue,org.objectweb.asm.tree.analysis.BasicValue) +meth public org.objectweb.asm.tree.analysis.BasicValue newValue(org.objectweb.asm.Type) +meth public void setClassLoader(java.lang.ClassLoader) +supr org.objectweb.asm.tree.analysis.BasicVerifier +hfds currentClass,currentClassInterfaces,currentSuperClass,isInterface,loader + +CLSS public org.objectweb.asm.tree.analysis.SourceInterpreter +cons protected init(int) +cons public init() +intf org.objectweb.asm.Opcodes +meth public org.objectweb.asm.tree.analysis.SourceValue binaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue copyOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue merge(org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue naryOperation(org.objectweb.asm.tree.AbstractInsnNode,java.util.List) +meth public org.objectweb.asm.tree.analysis.SourceValue newOperation(org.objectweb.asm.tree.AbstractInsnNode) +meth public org.objectweb.asm.tree.analysis.SourceValue newValue(org.objectweb.asm.Type) +meth public org.objectweb.asm.tree.analysis.SourceValue ternaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +meth public org.objectweb.asm.tree.analysis.SourceValue unaryOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue) +meth public void returnOperation(org.objectweb.asm.tree.AbstractInsnNode,org.objectweb.asm.tree.analysis.SourceValue,org.objectweb.asm.tree.analysis.SourceValue) +supr org.objectweb.asm.tree.analysis.Interpreter + +CLSS public org.objectweb.asm.tree.analysis.SourceValue +cons public init(int) +cons public init(int,java.util.Set) +cons public init(int,org.objectweb.asm.tree.AbstractInsnNode) +fld public final int size +fld public final java.util.Set insns +intf org.objectweb.asm.tree.analysis.Value +meth public boolean equals(java.lang.Object) +meth public int getSize() +meth public int hashCode() +supr java.lang.Object + +CLSS public abstract interface org.objectweb.asm.tree.analysis.Value +meth public abstract int getSize() + diff --git a/asm-commons/src/main/java/org/objectweb/asm/commons/AdviceAdapter.java b/asm-commons/src/main/java/org/objectweb/asm/commons/AdviceAdapter.java new file mode 100644 index 000000000..feb346262 --- /dev/null +++ b/asm-commons/src/main/java/org/objectweb/asm/commons/AdviceAdapter.java @@ -0,0 +1,644 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.commons; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * A {@link MethodVisitor} to insert before, after and around advices in methods and constructors. + * + *

The behavior for constructors is the following: + * + *

    + *
  1. as long as the INVOKESPECIAL for the object initialization has not been reached, every + * bytecode instruction is dispatched in the ctor code visitor + *
  2. when this one is reached, it is only added in the ctor code visitor and a JP invoke is + * added + *
  3. after that, only the other code visitor receives the instructions + *
+ * + * @author Eugene Kuleshov + * @author Eric Bruneton + */ +public abstract class AdviceAdapter extends GeneratorAdapter implements Opcodes { + + /** The "uninitialized this" value. */ + private static final Object UNINITIALIZED_THIS = new Object(); + + /** Any value other than "uninitialized this". */ + private static final Object OTHER = new Object(); + + private static final String INVALID_OPCODE = "Invalid opcode "; + + /** The access flags of the visited method. */ + protected int methodAccess; + + /** The descriptor of the visited method. */ + protected String methodDesc; + + /** Whether the visited method is a constructor. */ + private boolean isConstructor; + + /** + * Whether the super class constructor has been called (if the visited method is a constructor). + */ + private boolean superClassConstructorCalled; + + /** + * The values on the current execution stack frame (long and double are represented by two + * elements). Each value is either {@link #UNINITIALIZED_THIS} (for the uninitialized this value), + * or {@link #OTHER} (for any other value). This field is only maintained for constructors, in + * branches where the super class constructor has not been called yet. + */ + private List stackFrame; + + /** + * The stack map frames corresponding to the labels of the forward jumps made before the super + * class constructor has been called (note that the Java Virtual Machine forbids backward jumps + * before the super class constructor is called). This field is only maintained for constructors. + */ + private Map> forwardJumpStackFrames; + + /** + * Constructs a new {@link AdviceAdapter}. + * + * @param api the ASM API version implemented by this visitor. Must be one of {@link + * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}. + * @param methodVisitor the method visitor to which this adapter delegates calls. + * @param access the method's access flags (see {@link Opcodes}). + * @param name the method's name. + * @param descriptor the method's descriptor (see {@link Type Type}). + */ + protected AdviceAdapter( + final int api, + final MethodVisitor methodVisitor, + final int access, + final String name, + final String descriptor) { + super(api, methodVisitor, access, name, descriptor); + methodAccess = access; + methodDesc = descriptor; + isConstructor = "".equals(name); + } + + @Override + public void visitCode() { + super.visitCode(); + if (isConstructor) { + stackFrame = new ArrayList(); + forwardJumpStackFrames = new HashMap>(); + } else { + onMethodEnter(); + } + } + + @Override + public void visitLabel(final Label label) { + super.visitLabel(label); + if (isConstructor && forwardJumpStackFrames != null) { + List labelStackFrame = forwardJumpStackFrames.get(label); + if (labelStackFrame != null) { + stackFrame = labelStackFrame; + superClassConstructorCalled = false; + forwardJumpStackFrames.remove(label); + } + } + } + + @Override + public void visitInsn(final int opcode) { + if (isConstructor && !superClassConstructorCalled) { + int stackSize; + switch (opcode) { + case IRETURN: + case FRETURN: + case ARETURN: + case LRETURN: + case DRETURN: + throw new IllegalArgumentException("Invalid return in constructor"); + case RETURN: // empty stack + onMethodExit(opcode); + break; + case ATHROW: // 1 before n/a after + popValue(); + onMethodExit(opcode); + break; + case NOP: + case LALOAD: // remove 2 add 2 + case DALOAD: // remove 2 add 2 + case LNEG: + case DNEG: + case FNEG: + case INEG: + case L2D: + case D2L: + case F2I: + case I2B: + case I2C: + case I2S: + case I2F: + case ARRAYLENGTH: + break; + case ACONST_NULL: + case ICONST_M1: + case ICONST_0: + case ICONST_1: + case ICONST_2: + case ICONST_3: + case ICONST_4: + case ICONST_5: + case FCONST_0: + case FCONST_1: + case FCONST_2: + case F2L: // 1 before 2 after + case F2D: + case I2L: + case I2D: + pushValue(OTHER); + break; + case LCONST_0: + case LCONST_1: + case DCONST_0: + case DCONST_1: + pushValue(OTHER); + pushValue(OTHER); + break; + case IALOAD: // remove 2 add 1 + case FALOAD: // remove 2 add 1 + case AALOAD: // remove 2 add 1 + case BALOAD: // remove 2 add 1 + case CALOAD: // remove 2 add 1 + case SALOAD: // remove 2 add 1 + case POP: + case IADD: + case FADD: + case ISUB: + case LSHL: // 3 before 2 after + case LSHR: // 3 before 2 after + case LUSHR: // 3 before 2 after + case L2I: // 2 before 1 after + case L2F: // 2 before 1 after + case D2I: // 2 before 1 after + case D2F: // 2 before 1 after + case FSUB: + case FMUL: + case FDIV: + case FREM: + case FCMPL: // 2 before 1 after + case FCMPG: // 2 before 1 after + case IMUL: + case IDIV: + case IREM: + case ISHL: + case ISHR: + case IUSHR: + case IAND: + case IOR: + case IXOR: + case MONITORENTER: + case MONITOREXIT: + popValue(); + break; + case POP2: + case LSUB: + case LMUL: + case LDIV: + case LREM: + case LADD: + case LAND: + case LOR: + case LXOR: + case DADD: + case DMUL: + case DSUB: + case DDIV: + case DREM: + popValue(); + popValue(); + break; + case IASTORE: + case FASTORE: + case AASTORE: + case BASTORE: + case CASTORE: + case SASTORE: + case LCMP: // 4 before 1 after + case DCMPL: + case DCMPG: + popValue(); + popValue(); + popValue(); + break; + case LASTORE: + case DASTORE: + popValue(); + popValue(); + popValue(); + popValue(); + break; + case DUP: + pushValue(peekValue()); + break; + case DUP_X1: + stackSize = stackFrame.size(); + stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1)); + break; + case DUP_X2: + stackSize = stackFrame.size(); + stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1)); + break; + case DUP2: + stackSize = stackFrame.size(); + stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1)); + stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1)); + break; + case DUP2_X1: + stackSize = stackFrame.size(); + stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1)); + stackFrame.add(stackSize - 3, stackFrame.get(stackSize - 1)); + break; + case DUP2_X2: + stackSize = stackFrame.size(); + stackFrame.add(stackSize - 4, stackFrame.get(stackSize - 1)); + stackFrame.add(stackSize - 4, stackFrame.get(stackSize - 1)); + break; + case SWAP: + stackSize = stackFrame.size(); + stackFrame.add(stackSize - 2, stackFrame.get(stackSize - 1)); + stackFrame.remove(stackSize); + break; + default: + throw new IllegalArgumentException(INVALID_OPCODE + opcode); + } + } else { + switch (opcode) { + case RETURN: + case IRETURN: + case FRETURN: + case ARETURN: + case LRETURN: + case DRETURN: + case ATHROW: + onMethodExit(opcode); + break; + default: + break; + } + } + super.visitInsn(opcode); + } + + @Override + public void visitVarInsn(final int opcode, final int var) { + super.visitVarInsn(opcode, var); + if (isConstructor && !superClassConstructorCalled) { + switch (opcode) { + case ILOAD: + case FLOAD: + pushValue(OTHER); + break; + case LLOAD: + case DLOAD: + pushValue(OTHER); + pushValue(OTHER); + break; + case ALOAD: + pushValue(var == 0 ? UNINITIALIZED_THIS : OTHER); + break; + case ASTORE: + case ISTORE: + case FSTORE: + popValue(); + break; + case LSTORE: + case DSTORE: + popValue(); + popValue(); + break; + default: + throw new IllegalArgumentException(INVALID_OPCODE + opcode); + } + } + } + + @Override + public void visitFieldInsn( + final int opcode, final String owner, final String name, final String descriptor) { + super.visitFieldInsn(opcode, owner, name, descriptor); + if (isConstructor && !superClassConstructorCalled) { + char firstDescriptorChar = descriptor.charAt(0); + boolean longOrDouble = firstDescriptorChar == 'J' || firstDescriptorChar == 'D'; + switch (opcode) { + case GETSTATIC: + pushValue(OTHER); + if (longOrDouble) { + pushValue(OTHER); + } + break; + case PUTSTATIC: + popValue(); + if (longOrDouble) { + popValue(); + } + break; + case PUTFIELD: + popValue(); + popValue(); + if (longOrDouble) { + popValue(); + } + break; + case GETFIELD: + if (longOrDouble) { + pushValue(OTHER); + } + break; + default: + throw new IllegalArgumentException(INVALID_OPCODE + opcode); + } + } + } + + @Override + public void visitIntInsn(final int opcode, final int operand) { + super.visitIntInsn(opcode, operand); + if (isConstructor && !superClassConstructorCalled && opcode != NEWARRAY) { + pushValue(OTHER); + } + } + + @Override + public void visitLdcInsn(final Object value) { + super.visitLdcInsn(value); + if (isConstructor && !superClassConstructorCalled) { + pushValue(OTHER); + if (value instanceof Double || value instanceof Long) { + pushValue(OTHER); + } + } + } + + @Override + public void visitMultiANewArrayInsn(final String descriptor, final int numDimensions) { + super.visitMultiANewArrayInsn(descriptor, numDimensions); + if (isConstructor && !superClassConstructorCalled) { + for (int i = 0; i < numDimensions; i++) { + popValue(); + } + pushValue(OTHER); + } + } + + @Override + public void visitTypeInsn(final int opcode, final String type) { + super.visitTypeInsn(opcode, type); + // ANEWARRAY, CHECKCAST or INSTANCEOF don't change stack. + if (isConstructor && !superClassConstructorCalled && opcode == NEW) { + pushValue(OTHER); + } + } + + /** @deprecated */ + @Deprecated + @Override + public void visitMethodInsn( + final int opcode, final String owner, final String name, final String descriptor) { + if (api >= Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, descriptor); + return; + } + mv.visitMethodInsn(opcode, owner, name, descriptor, opcode == Opcodes.INVOKEINTERFACE); + doVisitMethodInsn(opcode, descriptor); + } + + @Override + public void visitMethodInsn( + final int opcode, + final String owner, + final String name, + final String descriptor, + final boolean isInterface) { + if (api < Opcodes.ASM5) { + super.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + return; + } + mv.visitMethodInsn(opcode, owner, name, descriptor, isInterface); + doVisitMethodInsn(opcode, descriptor); + } + + private void doVisitMethodInsn(final int opcode, final String descriptor) { + if (isConstructor && !superClassConstructorCalled) { + for (Type argumentType : Type.getArgumentTypes(descriptor)) { + popValue(); + if (argumentType.getSize() == 2) { + popValue(); + } + } + switch (opcode) { + case INVOKEINTERFACE: + case INVOKEVIRTUAL: + popValue(); + break; + case INVOKESPECIAL: + Object value = popValue(); + if (value == UNINITIALIZED_THIS && !superClassConstructorCalled) { + onMethodEnter(); + superClassConstructorCalled = true; + } + break; + default: + break; + } + + Type returnType = Type.getReturnType(descriptor); + if (returnType != Type.VOID_TYPE) { + pushValue(OTHER); + if (returnType.getSize() == 2) { + pushValue(OTHER); + } + } + } + } + + @Override + public void visitInvokeDynamicInsn( + final String name, + final String descriptor, + final Handle bootstrapMethodHandle, + final Object... bootstrapMethodArguments) { + super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments); + doVisitMethodInsn(Opcodes.INVOKEDYNAMIC, descriptor); + } + + @Override + public void visitJumpInsn(final int opcode, final Label label) { + super.visitJumpInsn(opcode, label); + if (isConstructor && !superClassConstructorCalled) { + switch (opcode) { + case IFEQ: + case IFNE: + case IFLT: + case IFGE: + case IFGT: + case IFLE: + case IFNULL: + case IFNONNULL: + popValue(); + break; + case IF_ICMPEQ: + case IF_ICMPNE: + case IF_ICMPLT: + case IF_ICMPGE: + case IF_ICMPGT: + case IF_ICMPLE: + case IF_ACMPEQ: + case IF_ACMPNE: + popValue(); + popValue(); + break; + case JSR: + pushValue(OTHER); + break; + default: + break; + } + addForwardJump(label); + } + } + + @Override + public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { + super.visitLookupSwitchInsn(dflt, keys, labels); + if (isConstructor && !superClassConstructorCalled) { + popValue(); + addForwardJumps(dflt, labels); + } + } + + @Override + public void visitTableSwitchInsn( + final int min, final int max, final Label dflt, final Label... labels) { + super.visitTableSwitchInsn(min, max, dflt, labels); + if (isConstructor && !superClassConstructorCalled) { + popValue(); + addForwardJumps(dflt, labels); + } + } + + @Override + public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { + super.visitTryCatchBlock(start, end, handler, type); + if (isConstructor + && !superClassConstructorCalled + && !forwardJumpStackFrames.containsKey(handler)) { + List handlerStackFrame = new ArrayList(); + handlerStackFrame.add(OTHER); + forwardJumpStackFrames.put(handler, handlerStackFrame); + } + } + + private void addForwardJumps(final Label dflt, final Label[] labels) { + addForwardJump(dflt); + for (Label label : labels) { + addForwardJump(label); + } + } + + private void addForwardJump(final Label label) { + if (forwardJumpStackFrames.containsKey(label)) { + return; + } + forwardJumpStackFrames.put(label, new ArrayList(stackFrame)); + } + + private Object popValue() { + return stackFrame.remove(stackFrame.size() - 1); + } + + private Object peekValue() { + return stackFrame.get(stackFrame.size() - 1); + } + + private void pushValue(final Object value) { + stackFrame.add(value); + } + + /** + * Generates the "before" advice for the visited method. The default implementation of this method + * does nothing. Subclasses can use or change all the local variables, but should not change state + * of the stack. This method is called at the beginning of the method or after super class + * constructor has been called (in constructors). + */ + protected void onMethodEnter() {} + + /** + * Generates the "after" advice for the visited method. The default implementation of this method + * does nothing. Subclasses can use or change all the local variables, but should not change state + * of the stack. This method is called at the end of the method, just before return and athrow + * instructions. The top element on the stack contains the return value or the exception instance. + * For example: + * + *
+   * public void onMethodExit(final int opcode) {
+   *   if (opcode == RETURN) {
+   *     visitInsn(ACONST_NULL);
+   *   } else if (opcode == ARETURN || opcode == ATHROW) {
+   *     dup();
+   *   } else {
+   *     if (opcode == LRETURN || opcode == DRETURN) {
+   *       dup2();
+   *     } else {
+   *       dup();
+   *     }
+   *     box(Type.getReturnType(this.methodDesc));
+   *   }
+   *   visitIntInsn(SIPUSH, opcode);
+   *   visitMethodInsn(INVOKESTATIC, owner, "onExit", "(Ljava/lang/Object;I)V");
+   * }
+   *
+   * // An actual call back method.
+   * public static void onExit(final Object exitValue, final int opcode) {
+   *   ...
+   * }
+   * 
+ * + * @param opcode one of {@link Opcodes#RETURN}, {@link Opcodes#IRETURN}, {@link Opcodes#FRETURN}, + * {@link Opcodes#ARETURN}, {@link Opcodes#LRETURN}, {@link Opcodes#DRETURN} or {@link + * Opcodes#ATHROW}. + */ + protected void onMethodExit(final int opcode) {} +} \ No newline at end of file diff --git a/asm-commons/src/main/java/org/objectweb/asm/commons/AnalyzerAdapter.java b/asm-commons/src/main/java/org/objectweb/asm/commons/AnalyzerAdapter.java new file mode 100644 index 000000000..4dd34c044 --- /dev/null +++ b/asm-commons/src/main/java/org/objectweb/asm/commons/AnalyzerAdapter.java @@ -0,0 +1,929 @@ +// ASM: a very small and fast Java bytecode manipulation framework +// Copyright (c) 2000-2011 INRIA, France Telecom +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holders nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +// THE POSSIBILITY OF SUCH DAMAGE. +package org.objectweb.asm.commons; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.ConstantDynamic; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; + +/** + * A {@link MethodVisitor} that keeps track of stack map frame changes between {@link + * #visitFrame(int, int, Object[], int, Object[])} calls. This adapter must be used with the {@link + * org.objectweb.asm.ClassReader#EXPAND_FRAMES} option. Each visitX instruction delegates to + * the next visitor in the chain, if any, and then simulates the effect of this instruction on the + * stack map frame, represented by {@link #locals} and {@link #stack}. The next visitor in the chain + * can get the state of the stack map frame before each instruction by reading the value of + * these fields in its visitX methods (this requires a reference to the AnalyzerAdapter that + * is before it in the chain). If this adapter is used with a class that does not contain stack map + * table attributes (i.e., pre Java 6 classes) then this adapter may not be able to compute the + * stack map frame for each instruction. In this case no exception is thrown but the {@link #locals} + * and {@link #stack} fields will be null for these instructions. + * + * @author Eric Bruneton + */ +public class AnalyzerAdapter extends MethodVisitor { + + /** + * The local variable slots for the current execution frame. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and + * double are represented by two elements, the second one being TOP). Reference types are + * represented by String objects (representing internal names), and uninitialized types by Label + * objects (this label designates the NEW instruction that created this uninitialized value). This + * field is null for unreachable instructions. + */ + public List locals; + + /** + * The operand stack slots for the current execution frame. Primitive types are represented by + * {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link Opcodes#FLOAT}, {@link Opcodes#LONG}, + * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or {@link Opcodes#UNINITIALIZED_THIS} (long and + * double are represented by two elements, the second one being TOP). Reference types are + * represented by String objects (representing internal names), and uninitialized types by Label + * objects (this label designates the NEW instruction that created this uninitialized value). This + * field is null for unreachable instructions. + */ + public List stack; + + /** The labels that designate the next instruction to be visited. May be null. */ + private List