Monday, August 31, 2009

Appease the serialization gods (and other interesting comments from the Java sources)

And now something completely different: I've studied the Java sources quite a bit and I've learned a bunch. I've also come across some pretty funny, strange and unexpected comments. Here's my categorized compilation of the most interesting ones.

Funny

java.math.BigDecimal:
001 /* Appease the serialization gods */
002 
private static final long serialVersionUID = 6108874887143696463L;

java.util.ArrayDeque:
001 /**
002  * Appease the serialization gods.
003  */
004 
private static final long serialVersionUID = 2340985798034038923L;

com.sun.corba.se.impl.naming.cosnaming.NamingContextImpl:
001     if (impl.Resolve(n[0],bth) != null)
002     
// "Resistence is futile." [Borg pickup line]
003 
    throw new AlreadyBound();

java.awt.Dialog:
001     // add all blockers' blockers to blockers :)
002 
    for (int i = 0; i < blockers.size(); i++) {

Animator (Demo classes):
001     /**
002      * Stop the insanity, um, applet.
003      */
004 
    public synchronized void stop() {
005         engine = null;
006         animation.stopPlaying();
007         
if (userPause) {
008             userPause = false;
009             notify();
010         }
011     }

javax.swing.text.rtf.RTFGenerator:
001 String approximationForUnicode(char ch)
002 {
003     
/* TODO: Find reasonable approximations for all Unicode characters
004        in all RTF code pages... heh, heh... */
005 
    return "?";
006 }

(Sorry, this typo is an inside joke and will only be funny to one person - you know who you are ;)
com.sun.corba.se.impl.oa.poa.POAImpl:
001 /**
002  * POAImpl is the implementation of the Portable Object Adapter. It
003  * contains an implementation of the POA interfaces specified in
004  * COBRA 2.3.1 chapter 11 (formal/99-10-07).
005 ...
006  */


Resigned

javax.swing.Timer:
001 // This of course implies you can get dropped events, but such is life.

sun.plugin2.ipc.windows.WindowsIPCFactory:
001 // Might as well keep this around

sun.media.sound.MixerSourceLine:
001 // ivg: Well, it does hang in some cases.

sun.security.x509.AVA:
001     if (!in.markSupported()) {
002         
// oh well
003 
        return true;
004     } 
else {


Informational

sun.tools.java.ClassDefinition:
001  // Why are they called Miranda methods? Well the sentence "If the
002 
 // class is not able to provide a method, then one will be provided
003 
 // by the compiler" is very similar to the sentence "If you cannot
004 
 // afford an attorney, one will be provided by the court," -- one
005 
 // of the so-called "Miranda" rights in the United States.


Frustrated

javax.swing.JTabbedPane
001  // REMIND(aim): this is really silly;

com.sun.xml.internal.bind.v2.util.DataSourceSource:
001     } catch (IOException e) {
002         
// argh
003 
        throw new RuntimeException(e);
004     }

com.sun.org.apache.xml.internal.serialize.HTMLdtd:
001 public static boolean isURI( String tagName, String attrName )
002 {
003     
// Stupid checks.
004 
    return ( attrName.equalsIgnoreCase( "href" ) || attrName.equalsIgnoreCase( "src" ) );
005 }

javax.swing.text.rtf.AbstractFilter:
001     // stupid signed bytes
002 
    if (b < 0)
003         b += 256;

com.sun.org.apache.xalan.internal.xsltc.trax.TransformerHandlerImpl:
001     catch (TransformerException e) {
002         
// What the hell are we supposed to do with this???
003 
        throw new IllegalArgumentException(e.getMessage());
004     }

sun.misc.FloatingDecimal:
001     if ( diff != 0L ) {
002         
// damn, damn, damn. q is too big.

sun.xml.internal.stream.writers.XMLDOMWriterImpl:
001     public void writeEndDocument() throws XMLStreamException {
002         
//What do you want me to do eh! :)

com.sun.org.apache.xml.internal.res.XMLMessages:
001  // Do this to keep format from crying.


Amused

sun.awt.X11.XWM:
001 /*
002  * Helper function for isEnlightenment().
003  * Enlightenment uses STRING property for its comms window id.  Gaaa!
004  * The property is ENLIGHTENMENT_COMMS, STRING/8 and the string format
005  * is "WINID %8x".  Gee, I haven't been using scanf for *ages*... :-)
006  */


Agressive

com.sun.org.apache.xalan.internal.xslt.Process:
001   /** It is _much_ easier to debug under VJ++ if I can set a single breakpoint
002    * before this blows itself out of the water...
003    * (I keep checking this in, it keeps vanishing. Grr!)
004    * */
005 
  static void doExit(String msg)
006   {
007     
throw new RuntimeException(msg);
008   }

com.sun.org.apache.xalan.internal.xsltc.dom.BitArray:
001 /**
002  * This method returns the Nth bit that is set in the bit array. The
003  * current position is cached in the following 4 variables and will
004  * help speed up a sequence of next() call in an index iterator. This
005  * method is a mess, but it is fast and it works, so don't fuck with it.
006  */

Playful

sun.awt.motif.MWindowPeer:
001     // XXX: nasty WM, foul play. spank WM author.
002 
    public void handleDestroy() {

DirectoryScanner (Example classes):
001     // As it stands, we simply call task.execute() in the current
002 
    // thread - brave and fearless readers may want to attempt the
003 
    // modification ;-)


Threatric

java.util.logging.LogManager:
001 if (deathImminent) {
002     
// Aaargh...
003 
    // The VM is shutting down and our exit hook has been called.
004 
    // Avoid allocating global handlers.
005 
    return;
006 }


Downright Crazy

javax.swing.text.rtf.MockAttributeSet:
001 /* This AttributeSet is made entirely out of tofu and Ritz Crackers
002    and yet has a remarkably attribute-set-like interface! */
003 
class MockAttributeSet
004     
implements AttributeSet, MutableAttributeSet

(This has been featured on the dailywtf in the past)
com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl:
001 /**
002  * As Gregor Samsa awoke one morning from uneasy dreams he found himself
003  * transformed in his bed into a gigantic insect. He was lying on his hard,
004  * as it were armour plated, back, and if he lifted his head a little he
005  * could see his big, brown belly divided into stiff, arched segments, on
006  * top of which the bed quilt could hardly keep in position and was about
007  * to slide off completely. His numerous legs, which were pitifully thin
008  * compared to the rest of his bulk, waved helplessly before his eyes.
009  * "What has happened to me
010  */
011 
protected final static String DEFAULT_TRANSLET_NAME = "GregorSamsa";


Joyous

com.sun.org.apache.xml.internal.serializer.utils.Messages:
001  fmsg = java.text.MessageFormat.format(msg, args);
002  
// if we get past the line above we have create the message ... hurray!


Sarcastic

com.sun.org.apache.xpath.internal.axes.WalkerFactory:
001 // If we have an attribute or namespace axis that went up, then
002 // it won't find the attribute in the inverse, since the select-to-match
003 // axes are not invertable (an element is a parent of an attribute, but
004 // and attribute is not a child of an element).
005 // If we don't do the magic below, then "@*/ancestor-or-self::*" gets
006 // inverted for match to "self::*/descendant-or-self::@*/parent::node()",
007 // which obviously won't work.
008 // So we will rewrite this as:
009 // "self::*/descendant-or-self::*/attribute::*/parent::node()"
010 // Child has to be rewritten a little differently:
011 // select: "@*/parent::*"
012 // inverted match: "self::*/child::@*/parent::node()"
013 // rewrite: "self::*/attribute::*/parent::node()"
014 // Axes that go down in the select, do not have to have special treatment
015 // in the rewrite. The following inverted match will still not select
016 // anything.
017 // select: "@*/child::*"
018 // inverted match: "self::*/parent::@*/parent::node()"
019 // Lovely business, this.


Disgusted

com.sun.tools.internal.xjc.reader.xmlschema.SimpleTypeBuilder:
001     // TODO: this is so dumb
002 
    m.put("string",         CBuiltinLeafInfo.STRING);
003     m.put(
"anyURI",         CBuiltinLeafInfo.STRING);
004     m.put(
"boolean",        CBuiltinLeafInfo.BOOLEAN);

com.sun.tools.example.debug.bdi.JDIEventSource:
001 //### Gross foul hackery!
002 
private void dispatchEventSet(final AbstractEventSet es) {

javax.swing.tree.FixedHeightLayoutCache:
001     // YECK!
002 
    return getRow() + 1 + getTotalChildCount() -
003                  (childCount - index);

com.sun.org.apache.xpath.internal.axes.LocPathIterator:
001     // Yech, shouldn't have to do this. -sb
002 
    if(null == m_prefixResolver)
003         m_prefixResolver = xctxt.getNamespaceContext();
004 
005 ...
006       clone.m_predCount = m_predicateIndex;
007       
// The line above used to be:
008 
      // clone.m_predCount = predCount - 1;
009 
      // ...which looks like a dumb bug to me. -sb

com.sun.media.sound.MixerClip:
001 // i don't think we should allow this in this release: too many ways to screw up!
002 /*
003   //        // if we have a sample voice, update it
004   //        if (id != 0) {
005   //            // can throw IllegalArgumentException
006   //            // 
007   //            nSetLoopPoints(id, (int)start, (int)end);
008   //        }
009 */
...
001 /*
002 ...
003 if (Printer.err) Printer.err("Could not re-open clip in MixerClip.java.setLoopPoints!");
004 // we are screwed... re-open failed!
005 // sorry....
006 implClose();
007 ...
008 */

com.sun.deploy.util.VersionID:
001 // FIXME: this is a horrendously inefficient representation;
002 // should use an array of ints or Integers rather than re-parsing
003 // them every time

com.sun.org.apache.xml.internal.dtm.ref.IncrementalSAXSource_Filter:
001     // Horrendous kluge to run filter to completion. See below.
002 
    if(fNoMoreEvents)
003       
return;

Notepad (Demo Classes):
001 /**
002  * To shutdown when run as an application.  This is a
003  * fairly lame implementation.   A more self-respecting
004  * implementation would at least check to see if a save
005  * was needed.
006  */
007 
protected static final class AppCloser extends WindowAdapter {
008     
public void windowClosing(WindowEvent e) {
009         System.exit(0);
010     }
011 }


Other

sun.jkernel.DigestOutputStream:
001 catch (NoSuchAlgorithmException e) {
002     
// Impossible to get here, but stranger things have happened...
003 
    throw new RuntimeException("DigestOutputStream() unknown algorithm");
004 }
005 
// superstition from a test failure this.out = out;

com.sun.org.apache.xalan.internal.xsltc.dom.CachedDocument:
001 // Brutal handling of all exceptions
002 
catch (Exception e) {
003     
return(System.currentTimeMillis());
004 }

com.sun.java.util.jar.pack.PackageWriter:
001 // Crash and burn with a complaint if there are funny
002 // bytecodes in this class file.
003 
String complaint = code.getMethod()
004     +
" contains an unrecognized bytecode "+i
005     +
"; please use the pass-file option on this class.";
006 Utils.log.warning(complaint);
007 
throw new IOException(complaint);

java.util.jar.Pack200:
001 /**
002 ...
003  * Examples:
004  *     Map p = packer.properties();
005  *     p.put(PASS_FILE_PFX+0, "mutants/Rogue.class");
006  *     p.put(PASS_FILE_PFX+1, "mutants/Wolverine.class");
007  *     p.put(PASS_FILE_PFX+2, "mutants/Storm.class");
008  *     # Pass all files in an entire directory hierarchy:
009  *     p.put(PASS_FILE_PFX+3, "police/");
010  */

com.sun.tools.jdi.ObjectReferenceImpl:
001 /* The above code is left over from previous versions.
002  * We haven't had time to divine the intent.  jjh, 7/31/2003
003  */

com.sun.media.sound.RealTimeSequencer:
001 catch (MidiUnavailableException mue) {
002 
// uhum, strange situation. Need to cast to InvalidMidiDataException
003 
throw new InvalidMidiDataException(mue.getMessage());
004 }

com.sun.org.apache.xml.internal.dtm.ref.dom2dtm.DOM2DTM:
001 // (If it's an EntityReference node, we're probably scrod. For now
002 // I'm just hoping nobody is ever quite that foolish... %REVIEW%)

com.sun.tools.doclets.formats.html.AbstractTreeWriter:
001 /**
002  * Generate each level of the class tree. For each sub-class or
003  * sub-interface indents the next level information.
004  * Recurses itself to generate subclasses info.
005  * To iterate is human, to recurse is divine - L. Peter Deutsch.
006  *
007  * @param parent the superclass or superinterface of the list.
008  * @param list list of the sub-classes at this level.
009  * @param isEnum true if we are generating a tree for enums.
010  */

sun.awt.shell.Win32ShellFolder2:
001 // Ouch, we have no hard drives. Return something "valid" anyway.
002 
return new File("C:\\");

com.sun.org.apache.bcel.internal.ExceptionConstants:
001   /** The mother of all exceptions
002    */
003 
  public static final Class THROWABLE = Throwable.class;

com.sun.xml.internal.messaging.saaj.util.ByteOutputStream:
001 /**
002  * Evil buffer reallocation method.
003  * Don't use it unless you absolutely have to.
004  *
005  * @deprecated
006  *      because this is evil!
007  */
008 
public byte toByteArray()[] {
009     
byte[] newbuf = new byte[count];
010     System.arraycopy(buf, 0, newbuf, 0, count);
011     
return newbuf;
012 }

com.sun.org.apache.xpath.internal.compiler.Compiler:
001   int what = getWhatToShow(startOpPos);
002   
// bit-o-hackery, but this code is due for the morgue anyway...
003 
  if(0x00000500 == what)
004     addMagicSelf = false;

sun.jvm.hotspot.runtime.sparc.SPARCFrame:
001 // Also not sure exactly how alignment works...maybe should read these offsets from the target VM
002 // (When you have a hammer, everything looks like a nail)
003 
long offset = VM.getVM().alignUp(4, VM.getVM().getAddressSize());   // uc_flags

sun.security.tools.KeyTool:
001 // do not drown user with the help lines.
002 
if (debug) {
003     
throw new RuntimeException("NO BIG ERROR, SORRY");
004 } 
else {
005     System.exit(1);
006 }

Wednesday, August 05, 2009

java.net.Proxy and (Im)mutability

Java 6 update 15 fixed some stuff regarding to java.net.Proxy

Quoting:
A security vulnerability in the Java Runtime Environment proxy mechanism implementation may allow an untrusted applet or Java Web Start application to make non-authorized socket or URL connections to hosts other than the origin host.

I'm assuming Sun is referring to something I'd come across a couple months ago myself. I was looking into some things at java.net and came across the Proxy class. The Proxy class javadoc says
A Proxy is an immutable object.

Yet the class is public and non-final. It's methods are non-final, too. If you don't see the problem, go a few posts back to the bit that talks about immutability.

Didn't look at the fix yet, but Proxy was very much mutable and so it was possible to create a Proxy object which uses TOCTOU to connect to a host other than the originating host. The proxy has a method which returns the address and a mutable Proxy can be made to return the originating host to the security check and some other address for the actual connection.

I'd done an ultraquick PoC, but hadn't gotten around to warning Sun (not that they needed my help from the look of it), because I was working on some more interesting things.

JDK13Services - Thanks!

Sami Koivu acknowledges with thanks Sun Microsystems' thankful acknowledgement.

On a more serious note: Good job, Sun. I liked the fix, it's straightforward, simple and looks foolproof.

Tuesday, August 04, 2009

No Anniversary for JDK13Services

Java 6 update 15 fixes the simplest Java security bug I've found so far. And just before its anniversary (August 18th), so no cake.

It's also the least serious of the bugs so I'm not terribly upset that it took close to a year to fix.

com.sun.media.sound.JDK13Services has a public, static method called getDefaultProviderClass which takes a Class object as a parameter and it returns the system property which corresponds with the full class name. The problem is (was) that you can create your own classes whose names coincide with security sensitive property names, such as user.home, user.name, etc.

The implication is one of privacy.

An example of reading the user.home property and outputting it to System.out in an applet.

001 package user;
002 
003 
public class PropertyThief extends java.applet.Applet {
004 
005     
public void start() {
006         String usrHome = com.sun.media.sound.JDK13Services.getDefaultProviderClassName(user.home.
class);
007         System.out.println(usrHome);
008     }
009 }
010 
011 
class home {}

This'll only work in a pre-update-15 Java. From the quick look into the new rt.jar bytecode, it looks like they're doing a bunch of if's now to limit the properties you can request.