diff options
| author | 2014-09-18 00:17:43 -0400 | |
|---|---|---|
| committer | 2014-09-18 00:17:43 -0400 | |
| commit | c65a64fc89169456febc1b4c953dbcfbafdc5f0e (patch) | |
| tree | 136b8145423724c8a3392ff89edc492262cc995d | |
| parent | changed "Show Calls" menu to search for calls to the default constructor when... (diff) | |
| download | enigma-c65a64fc89169456febc1b4c953dbcfbafdc5f0e.tar.gz enigma-c65a64fc89169456febc1b4c953dbcfbafdc5f0e.tar.xz enigma-c65a64fc89169456febc1b4c953dbcfbafdc5f0e.zip | |
added better error handling for source export
added checks to make sure we don't try to decopmile classes outside of the jar
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 29 | ||||
| -rw-r--r-- | src/cuchaz/enigma/TranslatingTypeLoader.java | 8 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 84 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 13 |
4 files changed, 80 insertions, 54 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 0847049e..1178ed60 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -200,6 +200,12 @@ public class Deobfuscator | |||
| 200 | className = classMapping.getDeobfName(); | 200 | className = classMapping.getDeobfName(); |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | // is this class even in the jar? | ||
| 204 | if( !m_jarIndex.containsObfClass( new ClassEntry( className ) ) ) | ||
| 205 | { | ||
| 206 | return null; | ||
| 207 | } | ||
| 208 | |||
| 203 | // set the type loader | 209 | // set the type loader |
| 204 | m_settings.setTypeLoader( new TranslatingTypeLoader( | 210 | m_settings.setTypeLoader( new TranslatingTypeLoader( |
| 205 | m_jar, | 211 | m_jar, |
| @@ -279,15 +285,22 @@ public class Deobfuscator | |||
| 279 | progress.onProgress( i++, deobfClassEntry.toString() ); | 285 | progress.onProgress( i++, deobfClassEntry.toString() ); |
| 280 | } | 286 | } |
| 281 | 287 | ||
| 282 | // get the source | 288 | try |
| 283 | String source = getSource( getSourceTree( obfClassEntry.getName() ) ); | 289 | { |
| 284 | 290 | // get the source | |
| 285 | // write the file | 291 | String source = getSource( getSourceTree( obfClassEntry.getName() ) ); |
| 286 | File file = new File( dirOut, deobfClassEntry.getName().replace( '.', '/' ) + ".java" ); | 292 | |
| 287 | file.getParentFile().mkdirs(); | 293 | // write the file |
| 288 | try( FileWriter out = new FileWriter( file ) ) | 294 | File file = new File( dirOut, deobfClassEntry.getName().replace( '.', '/' ) + ".java" ); |
| 295 | file.getParentFile().mkdirs(); | ||
| 296 | try( FileWriter out = new FileWriter( file ) ) | ||
| 297 | { | ||
| 298 | out.write( source ); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | catch( Throwable t ) | ||
| 289 | { | 302 | { |
| 290 | out.write( source ); | 303 | throw new Error( "Unable to deobfuscate class " + deobfClassEntry.toString() + " (" + obfClassEntry.toString() + ")", t ); |
| 291 | } | 304 | } |
| 292 | } | 305 | } |
| 293 | 306 | ||
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index e70093eb..d321421a 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -124,10 +124,11 @@ public class TranslatingTypeLoader implements ITypeLoader | |||
| 124 | ClassEntry obfClassEntry = m_obfuscatingTranslator.translateEntry( deobfClassEntry ); | 124 | ClassEntry obfClassEntry = m_obfuscatingTranslator.translateEntry( deobfClassEntry ); |
| 125 | 125 | ||
| 126 | // is this an inner class referenced directly? | 126 | // is this an inner class referenced directly? |
| 127 | if( m_jarIndex.getOuterClass( obfClassEntry.getName() ) != null ) | 127 | String obfOuterClassName = m_jarIndex.getOuterClass( obfClassEntry.getName() ); |
| 128 | if( obfOuterClassName != null ) | ||
| 128 | { | 129 | { |
| 129 | // this class doesn't really exist. Reference it by outer$inner instead | 130 | // this class doesn't really exist. Reference it by outer$inner instead |
| 130 | System.err.println( String.format( "WARNING: class %s referenced by bare inner name", deobfClassName ) ); | 131 | System.err.println( String.format( "WARNING: class %s referenced by bare inner name instead of via outer class %s", deobfClassName, obfOuterClassName ) ); |
| 131 | return null; | 132 | return null; |
| 132 | } | 133 | } |
| 133 | 134 | ||
| @@ -210,6 +211,9 @@ public class TranslatingTypeLoader implements ITypeLoader | |||
| 210 | // sanity checking | 211 | // sanity checking |
| 211 | assertClassName( c, deobfClassEntry ); | 212 | assertClassName( c, deobfClassEntry ); |
| 212 | 213 | ||
| 214 | // DEBUG | ||
| 215 | Util.writeClass( c ); | ||
| 216 | |||
| 213 | // we have a transformed class! | 217 | // we have a transformed class! |
| 214 | return c.toBytecode(); | 218 | return c.toBytecode(); |
| 215 | } | 219 | } |
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 7fac02de..1995cb80 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -162,11 +162,7 @@ public class Gui | |||
| 162 | @Override | 162 | @Override |
| 163 | public void onSelectClass( ClassEntry classEntry ) | 163 | public void onSelectClass( ClassEntry classEntry ) |
| 164 | { | 164 | { |
| 165 | if( m_reference != null ) | 165 | navigateTo( classEntry ); |
| 166 | { | ||
| 167 | m_controller.savePreviousReference( m_reference ); | ||
| 168 | } | ||
| 169 | m_controller.openDeclaration( classEntry ); | ||
| 170 | } | 166 | } |
| 171 | } ); | 167 | } ); |
| 172 | JScrollPane obfScroller = new JScrollPane( m_obfClasses ); | 168 | JScrollPane obfScroller = new JScrollPane( m_obfClasses ); |
| @@ -182,11 +178,7 @@ public class Gui | |||
| 182 | @Override | 178 | @Override |
| 183 | public void onSelectClass( ClassEntry classEntry ) | 179 | public void onSelectClass( ClassEntry classEntry ) |
| 184 | { | 180 | { |
| 185 | if( m_reference != null ) | 181 | navigateTo( classEntry ); |
| 186 | { | ||
| 187 | m_controller.savePreviousReference( m_reference ); | ||
| 188 | } | ||
| 189 | m_controller.openDeclaration( classEntry ); | ||
| 190 | } | 182 | } |
| 191 | } ); | 183 | } ); |
| 192 | JScrollPane deobfScroller = new JScrollPane( m_deobfClasses ); | 184 | JScrollPane deobfScroller = new JScrollPane( m_deobfClasses ); |
| @@ -247,7 +239,7 @@ public class Gui | |||
| 247 | break; | 239 | break; |
| 248 | 240 | ||
| 249 | case KeyEvent.VK_N: | 241 | case KeyEvent.VK_N: |
| 250 | openDeclaration(); | 242 | navigateTo( m_reference.entry ); |
| 251 | break; | 243 | break; |
| 252 | 244 | ||
| 253 | case KeyEvent.VK_P: | 245 | case KeyEvent.VK_P: |
| @@ -335,7 +327,7 @@ public class Gui | |||
| 335 | @Override | 327 | @Override |
| 336 | public void actionPerformed( ActionEvent event ) | 328 | public void actionPerformed( ActionEvent event ) |
| 337 | { | 329 | { |
| 338 | openDeclaration(); | 330 | navigateTo( m_reference.entry ); |
| 339 | } | 331 | } |
| 340 | } ); | 332 | } ); |
| 341 | menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_N, 0 ) ); | 333 | menu.setAccelerator( KeyStroke.getKeyStroke( KeyEvent.VK_N, 0 ) ); |
| @@ -379,22 +371,15 @@ public class Gui | |||
| 379 | Object node = path.getLastPathComponent(); | 371 | Object node = path.getLastPathComponent(); |
| 380 | if( node instanceof ClassInheritanceTreeNode ) | 372 | if( node instanceof ClassInheritanceTreeNode ) |
| 381 | { | 373 | { |
| 382 | if( m_reference != null ) | 374 | ClassInheritanceTreeNode classNode = (ClassInheritanceTreeNode)node; |
| 383 | { | 375 | navigateTo( new ClassEntry( classNode.getObfClassName() ) ); |
| 384 | m_controller.savePreviousReference( m_reference ); | ||
| 385 | } | ||
| 386 | m_controller.openDeclaration( new ClassEntry( ((ClassInheritanceTreeNode)node).getObfClassName() ) ); | ||
| 387 | } | 376 | } |
| 388 | else if( node instanceof MethodInheritanceTreeNode ) | 377 | else if( node instanceof MethodInheritanceTreeNode ) |
| 389 | { | 378 | { |
| 390 | MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode)node; | 379 | MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode)node; |
| 391 | if( methodNode.isImplemented() ) | 380 | if( methodNode.isImplemented() ) |
| 392 | { | 381 | { |
| 393 | if( m_reference != null ) | 382 | navigateTo( methodNode.getMethodEntry() ); |
| 394 | { | ||
| 395 | m_controller.savePreviousReference( m_reference ); | ||
| 396 | } | ||
| 397 | m_controller.openDeclaration( methodNode.getMethodEntry() ); | ||
| 398 | } | 383 | } |
| 399 | } | 384 | } |
| 400 | } | 385 | } |
| @@ -425,12 +410,12 @@ public class Gui | |||
| 425 | if( node instanceof ClassImplementationsTreeNode ) | 410 | if( node instanceof ClassImplementationsTreeNode ) |
| 426 | { | 411 | { |
| 427 | ClassImplementationsTreeNode classNode = (ClassImplementationsTreeNode)node; | 412 | ClassImplementationsTreeNode classNode = (ClassImplementationsTreeNode)node; |
| 428 | m_controller.openDeclaration( classNode.getClassEntry() ); | 413 | navigateTo( classNode.getClassEntry() ); |
| 429 | } | 414 | } |
| 430 | else if( node instanceof MethodImplementationsTreeNode ) | 415 | else if( node instanceof MethodImplementationsTreeNode ) |
| 431 | { | 416 | { |
| 432 | MethodImplementationsTreeNode methodNode = (MethodImplementationsTreeNode)node; | 417 | MethodImplementationsTreeNode methodNode = (MethodImplementationsTreeNode)node; |
| 433 | m_controller.openDeclaration( methodNode.getMethodEntry() ); | 418 | navigateTo( methodNode.getMethodEntry() ); |
| 434 | } | 419 | } |
| 435 | } | 420 | } |
| 436 | } | 421 | } |
| @@ -460,18 +445,14 @@ public class Gui | |||
| 460 | Object node = path.getLastPathComponent(); | 445 | Object node = path.getLastPathComponent(); |
| 461 | if( node instanceof ReferenceTreeNode ) | 446 | if( node instanceof ReferenceTreeNode ) |
| 462 | { | 447 | { |
| 463 | if( m_reference != null ) | ||
| 464 | { | ||
| 465 | m_controller.savePreviousReference( m_reference ); | ||
| 466 | } | ||
| 467 | ReferenceTreeNode<Entry,Entry> referenceNode = ((ReferenceTreeNode<Entry,Entry>)node); | 448 | ReferenceTreeNode<Entry,Entry> referenceNode = ((ReferenceTreeNode<Entry,Entry>)node); |
| 468 | if( referenceNode.getReference() != null ) | 449 | if( referenceNode.getReference() != null ) |
| 469 | { | 450 | { |
| 470 | m_controller.openReference( referenceNode.getReference() ); | 451 | navigateTo( referenceNode.getReference() ); |
| 471 | } | 452 | } |
| 472 | else | 453 | else |
| 473 | { | 454 | { |
| 474 | m_controller.openDeclaration( referenceNode.getEntry() ); | 455 | navigateTo( referenceNode.getEntry() ); |
| 475 | } | 456 | } |
| 476 | } | 457 | } |
| 477 | } | 458 | } |
| @@ -1028,6 +1009,7 @@ public class Gui | |||
| 1028 | boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; | 1009 | boolean isFieldEntry = isToken && m_reference.entry instanceof FieldEntry; |
| 1029 | boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; | 1010 | boolean isMethodEntry = isToken && m_reference.entry instanceof MethodEntry; |
| 1030 | boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; | 1011 | boolean isConstructorEntry = isToken && m_reference.entry instanceof ConstructorEntry; |
| 1012 | boolean isInJar = isToken && m_controller.entryIsInJar( m_reference.entry.getClassEntry() ); | ||
| 1031 | 1013 | ||
| 1032 | if( isToken ) | 1014 | if( isToken ) |
| 1033 | { | 1015 | { |
| @@ -1038,14 +1020,42 @@ public class Gui | |||
| 1038 | clearReference(); | 1020 | clearReference(); |
| 1039 | } | 1021 | } |
| 1040 | 1022 | ||
| 1041 | m_renameMenu.setEnabled( isToken ); | 1023 | m_renameMenu.setEnabled( isInJar && isToken ); |
| 1042 | m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); | 1024 | m_showInheritanceMenu.setEnabled( isClassEntry || isMethodEntry || isConstructorEntry ); |
| 1043 | m_showImplementationsMenu.setEnabled( isClassEntry || isMethodEntry ); | 1025 | m_showImplementationsMenu.setEnabled( isClassEntry || isMethodEntry ); |
| 1044 | m_showCallsMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); | 1026 | m_showCallsMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); |
| 1045 | m_openEntryMenu.setEnabled( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ); | 1027 | m_openEntryMenu.setEnabled( isInJar && ( isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry ) ); |
| 1046 | m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() ); | 1028 | m_openPreviousMenu.setEnabled( m_controller.hasPreviousLocation() ); |
| 1047 | } | 1029 | } |
| 1048 | 1030 | ||
| 1031 | private void navigateTo( Entry entry ) | ||
| 1032 | { | ||
| 1033 | if( !m_controller.entryIsInJar( entry ) ) | ||
| 1034 | { | ||
| 1035 | // entry is not in the jar. Ignore it | ||
| 1036 | return; | ||
| 1037 | } | ||
| 1038 | if( m_reference != null ) | ||
| 1039 | { | ||
| 1040 | m_controller.savePreviousReference( m_reference ); | ||
| 1041 | } | ||
| 1042 | m_controller.openDeclaration( entry ); | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | private void navigateTo( EntryReference<Entry,Entry> reference ) | ||
| 1046 | { | ||
| 1047 | if( !m_controller.entryIsInJar( reference.getClassEntry() ) ) | ||
| 1048 | { | ||
| 1049 | // reference is not in the jar. Ignore it | ||
| 1050 | return; | ||
| 1051 | } | ||
| 1052 | if( m_reference != null ) | ||
| 1053 | { | ||
| 1054 | m_controller.savePreviousReference( m_reference ); | ||
| 1055 | } | ||
| 1056 | m_controller.openReference( reference ); | ||
| 1057 | } | ||
| 1058 | |||
| 1049 | private void startRename( ) | 1059 | private void startRename( ) |
| 1050 | { | 1060 | { |
| 1051 | // init the text box | 1061 | // init the text box |
| @@ -1232,16 +1242,6 @@ public class Gui | |||
| 1232 | return new TreePath( nodes.toArray() ); | 1242 | return new TreePath( nodes.toArray() ); |
| 1233 | } | 1243 | } |
| 1234 | 1244 | ||
| 1235 | private void openDeclaration( ) | ||
| 1236 | { | ||
| 1237 | if( m_reference == null ) | ||
| 1238 | { | ||
| 1239 | return; | ||
| 1240 | } | ||
| 1241 | m_controller.savePreviousReference( m_reference ); | ||
| 1242 | m_controller.openDeclaration( m_reference.entry ); | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | private void close( ) | 1245 | private void close( ) |
| 1246 | { | 1246 | { |
| 1247 | if( !m_controller.isDirty() ) | 1247 | if( !m_controller.isDirty() ) |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index c0fb2e40..3f54ecd4 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -170,7 +170,7 @@ public class GuiController | |||
| 170 | return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); | 170 | return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | public boolean entryIsObfuscatedIdenfitier( Entry deobfEntry ) | 173 | public boolean entryIsInJar( Entry deobfEntry ) |
| 174 | { | 174 | { |
| 175 | return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); | 175 | return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); |
| 176 | } | 176 | } |
| @@ -268,6 +268,10 @@ public class GuiController | |||
| 268 | // get the reference target class | 268 | // get the reference target class |
| 269 | EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference ); | 269 | EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference( deobfReference ); |
| 270 | ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry(); | 270 | ClassEntry obfClassEntry = obfReference.getClassEntry().getOuterClassEntry(); |
| 271 | if( !m_deobfuscator.isObfuscatedIdentifier( obfClassEntry ) ) | ||
| 272 | { | ||
| 273 | throw new IllegalArgumentException( "Entry must be in the jar!" ); | ||
| 274 | } | ||
| 271 | if( m_currentObfClass == null || !m_currentObfClass.equals( obfClassEntry ) ) | 275 | if( m_currentObfClass == null || !m_currentObfClass.equals( obfClassEntry ) ) |
| 272 | { | 276 | { |
| 273 | // deobfuscate the class, then navigate to the reference | 277 | // deobfuscate the class, then navigate to the reference |
| @@ -347,6 +351,11 @@ public class GuiController | |||
| 347 | { | 351 | { |
| 348 | // decompile,deobfuscate the bytecode | 352 | // decompile,deobfuscate the bytecode |
| 349 | CompilationUnit sourceTree = m_deobfuscator.getSourceTree( classEntry.getClassName() ); | 353 | CompilationUnit sourceTree = m_deobfuscator.getSourceTree( classEntry.getClassName() ); |
| 354 | if( sourceTree == null ) | ||
| 355 | { | ||
| 356 | // decompilation of this class is not supported | ||
| 357 | return; | ||
| 358 | } | ||
| 350 | String source = m_deobfuscator.getSource( sourceTree ); | 359 | String source = m_deobfuscator.getSource( sourceTree ); |
| 351 | m_index = m_deobfuscator.getSourceIndex( sourceTree, source ); | 360 | m_index = m_deobfuscator.getSourceIndex( sourceTree, source ); |
| 352 | m_gui.setSource( m_index.getSource() ); | 361 | m_gui.setSource( m_index.getSource() ); |
| @@ -365,7 +374,7 @@ public class GuiController | |||
| 365 | { | 374 | { |
| 366 | deobfuscatedTokens.add( token ); | 375 | deobfuscatedTokens.add( token ); |
| 367 | } | 376 | } |
| 368 | else if( entryIsObfuscatedIdenfitier( reference.entry ) ) | 377 | else if( entryIsInJar( reference.entry ) ) |
| 369 | { | 378 | { |
| 370 | obfuscatedTokens.add( token ); | 379 | obfuscatedTokens.add( token ); |
| 371 | } | 380 | } |