diff options
| author | 2014-09-21 22:08:05 -0400 | |
|---|---|---|
| committer | 2014-09-21 22:08:05 -0400 | |
| commit | df06f4ddde5e255750edc4087cfba54823404909 (patch) | |
| tree | 78ccb4ca9683dbfca5e94e6bce42615e3acf8a0e /src/cuchaz/enigma/analysis/JarIndex.java | |
| parent | started unit testing for inner/anonymous class detection (diff) | |
| download | enigma-fork-df06f4ddde5e255750edc4087cfba54823404909.tar.gz enigma-fork-df06f4ddde5e255750edc4087cfba54823404909.tar.xz enigma-fork-df06f4ddde5e255750edc4087cfba54823404909.zip | |
improved inner/anonymous class detection
Diffstat (limited to 'src/cuchaz/enigma/analysis/JarIndex.java')
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 43e2bf6..c36e9cb 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -440,29 +440,17 @@ public class JarIndex | |||
| 440 | ClassEntry classEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); | 440 | ClassEntry classEntry = new ClassEntry( Descriptor.toJvmName( c.getName() ) ); |
| 441 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, constructor.getMethodInfo().getDescriptor() ); | 441 | ConstructorEntry constructorEntry = new ConstructorEntry( classEntry, constructor.getMethodInfo().getDescriptor() ); |
| 442 | 442 | ||
| 443 | // look at the synthetic types to get candidates for the outer class | 443 | // gather the classes from the illegally-set synthetic fields |
| 444 | Set<ClassEntry> candidateOuterClasses = Sets.newHashSet(); | 444 | Set<ClassEntry> illegallySetClasses = Sets.newHashSet(); |
| 445 | for( String type : syntheticFieldTypes ) | 445 | for( String type : syntheticFieldTypes ) |
| 446 | { | 446 | { |
| 447 | if( type.startsWith( "L" ) ) | 447 | if( type.startsWith( "L" ) ) |
| 448 | { | 448 | { |
| 449 | candidateOuterClasses.add( new ClassEntry( type.substring( 1, type.length() - 1 ) ) ); | 449 | ClassEntry outerClassEntry = new ClassEntry( type.substring( 1, type.length() - 1 ) ); |
| 450 | } | 450 | if( isSaneOuterClass( outerClassEntry, classEntry ) ) |
| 451 | } | 451 | { |
| 452 | 452 | illegallySetClasses.add( outerClassEntry ); | |
| 453 | // do we have an answer yet? | 453 | } |
| 454 | if( candidateOuterClasses.isEmpty() ) | ||
| 455 | { | ||
| 456 | continue; | ||
| 457 | } | ||
| 458 | else if( candidateOuterClasses.size() == 1 ) | ||
| 459 | { | ||
| 460 | ClassEntry outerClassEntry = candidateOuterClasses.iterator().next(); | ||
| 461 | |||
| 462 | // does this class make sense as an outer class? | ||
| 463 | if( !outerClassEntry.equals( classEntry ) ) | ||
| 464 | { | ||
| 465 | return outerClassEntry.getName(); | ||
| 466 | } | 454 | } |
| 467 | } | 455 | } |
| 468 | 456 | ||
| @@ -470,33 +458,82 @@ public class JarIndex | |||
| 470 | Set<ClassEntry> callerClasses = Sets.newHashSet(); | 458 | Set<ClassEntry> callerClasses = Sets.newHashSet(); |
| 471 | for( EntryReference<BehaviorEntry,BehaviorEntry> reference : getBehaviorReferences( constructorEntry ) ) | 459 | for( EntryReference<BehaviorEntry,BehaviorEntry> reference : getBehaviorReferences( constructorEntry ) ) |
| 472 | { | 460 | { |
| 473 | // is that one of our candidates? | 461 | // make sure it's not a call to super |
| 474 | if( candidateOuterClasses.contains( reference.context.getClassEntry() ) ) | 462 | if( reference.entry instanceof ConstructorEntry && reference.context instanceof ConstructorEntry ) |
| 463 | { | ||
| 464 | // is the entry a superclass of the context? | ||
| 465 | String calledClassName = reference.entry.getClassName(); | ||
| 466 | String callerSuperclassName = m_translationIndex.getSuperclassName( reference.context.getClassName() ); | ||
| 467 | if( callerSuperclassName != null && callerSuperclassName.equals( calledClassName ) ) | ||
| 468 | { | ||
| 469 | // it's a super call, skip | ||
| 470 | continue; | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | if( isSaneOuterClass( reference.context.getClassEntry(), classEntry ) ) | ||
| 475 | { | 475 | { |
| 476 | callerClasses.add( reference.context.getClassEntry() ); | 476 | callerClasses.add( reference.context.getClassEntry() ); |
| 477 | } | 477 | } |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | // do we have an answer yet? | 480 | // do we have an answer yet? |
| 481 | if( callerClasses.size() == 1 ) | 481 | if( callerClasses.isEmpty() ) |
| 482 | { | 482 | { |
| 483 | ClassEntry outerClassEntry = callerClasses.iterator().next(); | 483 | if( illegallySetClasses.size() == 1 ) |
| 484 | |||
| 485 | // does this class make sense as an outer class? | ||
| 486 | if( !outerClassEntry.equals( classEntry ) ) | ||
| 487 | { | 484 | { |
| 488 | return outerClassEntry.getName(); | 485 | return illegallySetClasses.iterator().next().getName(); |
| 486 | } | ||
| 487 | else | ||
| 488 | { | ||
| 489 | System.out.println( String.format( "WARNING: Unable to find outer class for %s. No caller and no illegally set field classes.", classEntry ) ); | ||
| 489 | } | 490 | } |
| 490 | } | 491 | } |
| 491 | else | 492 | else |
| 492 | { | 493 | { |
| 493 | System.out.println( "WARNING: Unable to choose outer class among options: " + candidateOuterClasses ); | 494 | if( callerClasses.size() == 1 ) |
| 495 | { | ||
| 496 | return callerClasses.iterator().next().getName(); | ||
| 497 | } | ||
| 498 | else | ||
| 499 | { | ||
| 500 | // multiple callers, do the illegally set classes narrow it down? | ||
| 501 | Set<ClassEntry> intersection = Sets.newHashSet( callerClasses ); | ||
| 502 | intersection.retainAll( illegallySetClasses ); | ||
| 503 | if( intersection.size() == 1 ) | ||
| 504 | { | ||
| 505 | return intersection.iterator().next().getName(); | ||
| 506 | } | ||
| 507 | else | ||
| 508 | { | ||
| 509 | System.out.println( String.format( "WARNING: Unable to choose outer class for %s among options: %s", | ||
| 510 | classEntry, callerClasses | ||
| 511 | ) ); | ||
| 512 | } | ||
| 513 | } | ||
| 494 | } | 514 | } |
| 495 | } | 515 | } |
| 496 | 516 | ||
| 497 | return null; | 517 | return null; |
| 498 | } | 518 | } |
| 499 | 519 | ||
| 520 | private boolean isSaneOuterClass( ClassEntry outerClassEntry, ClassEntry innerClassEntry ) | ||
| 521 | { | ||
| 522 | // clearly this would be silly | ||
| 523 | if( outerClassEntry.equals( innerClassEntry ) ) | ||
| 524 | { | ||
| 525 | return false; | ||
| 526 | } | ||
| 527 | |||
| 528 | // is the outer class in the jar? | ||
| 529 | if( !m_obfClassEntries.contains( outerClassEntry ) ) | ||
| 530 | { | ||
| 531 | return false; | ||
| 532 | } | ||
| 533 | |||
| 534 | return true; | ||
| 535 | } | ||
| 536 | |||
| 500 | @SuppressWarnings( "unchecked" ) | 537 | @SuppressWarnings( "unchecked" ) |
| 501 | private boolean isIllegalConstructor( Set<String> syntheticFieldTypes, CtConstructor constructor ) | 538 | private boolean isIllegalConstructor( Set<String> syntheticFieldTypes, CtConstructor constructor ) |
| 502 | { | 539 | { |