You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2005/09/21 09:20:42 UTC

svn commit: r290642 - /directory/asn1/trunk/ber-new/src/java/main/org/apache/asn1new/ber/Asn1Decoder.java

Author: elecharny
Date: Wed Sep 21 00:20:37 2005
New Revision: 290642

URL: http://svn.apache.org/viewcvs?rev=290642&view=rev
Log:
Fixed a bug in the decoder that leads to badly decode some PDU. The code has been fully rechecked, just in case.

Modified:
    directory/asn1/trunk/ber-new/src/java/main/org/apache/asn1new/ber/Asn1Decoder.java

Modified: directory/asn1/trunk/ber-new/src/java/main/org/apache/asn1new/ber/Asn1Decoder.java
URL: http://svn.apache.org/viewcvs/directory/asn1/trunk/ber-new/src/java/main/org/apache/asn1new/ber/Asn1Decoder.java?rev=290642&r1=290641&r2=290642&view=diff
==============================================================================
--- directory/asn1/trunk/ber-new/src/java/main/org/apache/asn1new/ber/Asn1Decoder.java (original)
+++ directory/asn1/trunk/ber-new/src/java/main/org/apache/asn1new/ber/Asn1Decoder.java Wed Sep 21 00:20:37 2005
@@ -98,69 +98,66 @@
     private boolean treatTagStartState( ByteBuffer stream, IAsn1Container container )
         throws DecoderException
     {
-
         if ( stream.hasRemaining() )
         {
-
             byte octet = stream.get();
-
+    
             TLV tlv = new TLV();
             Tag tag = tlv.getTag();
-
-            tag.setSize( 1 );
+    
             tag.setPrimitive( ( octet & Tag.CONSTRUCTED_FLAG ) == 0 );
             tag.setTypeClass( Tag.TYPE_CLASS[( octet & Tag.TYPE_CLASS_MASK ) >>> 6] );
-
+    
             int value = octet & Tag.SHORT_MASK;
-
+    
             if ( value == Tag.SHORT_MASK )
             {
-
+                // It's a tag wich value is above 31
                 // we have to check the typeClass. UNIVERSAL class is not
                 // allowed with this value.
                 if ( tag.isUniversal() )
                 {
                     throw new DecoderException( "Universal tag 31 is reserved" );
                 }
-
+    
                 // we will have more than one byte to encode the value
                 // The tag is encoded on [2 - 6 bytes], its value
-                // is container in the 7 lower bits of the bytes following
+                // is contained in the 7 lower bits of the bytes following
                 // the first byte.
                 container.setState( TLVStateEnum.TAG_STATE_PENDING );
                 tag.setId( 0 );
                 tag.addByte( octet );
+                tag.setSize( 0 );
             }
             else
             {
                 // It's a tag wich value is below 30 (31 is not allowed
-                // as it signals a multi-bytes value. Everything is done.
-
+                // as it signals a multi-bytes value). The tag's length is 1 byte
+                tag.setSize( 1 );
+    
                 // We have to check for reserved tags if typeClass is UNIVERSAL
                 if ( tag.isUniversal() )
                 {
-
                     if ( ( value == UniversalTag.RESERVED_14 ) || ( value == UniversalTag.RESERVED_15 ) )
                     {
                         throw new DecoderException( "Universal tag " + value + " is reserved" );
                     }
                 }
-
+    
                 tag.setId( value );
                 tag.addByte( octet );
-
+    
                 // The tag has been completed, we have to decode the Length
                 container.setState( TLVStateEnum.TAG_STATE_END );
             }
-
+    
             // Store the current TLV in the container.
             container.setCurrentTLV( tlv );
-
+            
             return MORE;
         }
         else
         {
-
             // The stream has been exhausted
             return END;
         }
@@ -182,40 +179,35 @@
     private boolean treatTagPendingState( ByteBuffer stream, IAsn1Container container )
         throws DecoderException
     {
-
         if ( stream.hasRemaining() )
         {
-
             Tag  tag    = container.getCurrentTLV().getTag();
             byte octet = stream.get();
-
+    
             if ( tag.getSize() >= Tag.MAX_TAG_BYTES )
             {
                 container.setState( TLVStateEnum.TAG_STATE_OVERFLOW );
                 log.error( "Tag label Overflow" );
                 throw new DecoderException( "Tag label overflow" );
             }
-
+    
             byte val = ( byte ) ( octet & Tag.LONG_MASK );
-
+    
             tag.setId( ( tag.getId() << 7 ) | val );
             tag.incTagSize();
-
+    
             if ( val == octet )
             {
-
                 // The Tag is completed, so let's decode the Length
                 container.setState( TLVStateEnum.LENGTH_STATE_START );
             }
-
+            
             return MORE;
         }
         else
         {
-
             return END;
         }
-
     }
 
     /**
@@ -227,25 +219,26 @@
         StringBuffer sb = new StringBuffer();
         TLV current = container.getCurrentTLV();
         
-        sb.append("TLV").
-        	append(StringUtils.dumpByte(current.getTag().getTagBytes()[0])).
-        	append("(").
-        	append(current.getExpectedLength()).
-        	append(")");
+        sb.append( "TLV" ).
+        	append( StringUtils.dumpByte( current.getTag().getTagBytes()[0] ) ).
+        	append( "(" ).
+        	append( current.getExpectedLength() ).
+        	append( ")" );
         
         current = current.getParent();
         
         while (current != null)
         {
-            sb.append("-TLV").
-        		append(StringUtils.dumpByte(current.getTag().getTagBytes()[0])).
-        		append("(").
-        		append(current.getExpectedLength()).
-        		append(")");
+            sb.append( "-TLV" ).
+        		append( StringUtils.dumpByte( current.getTag().getTagBytes()[0] ) ).
+        		append( "(" ).
+        		append( current.getExpectedLength() ).
+        		append( ")" );
+            
             current = current.getParent();
         }
         
-        log.debug("TLV Tree : " + sb.toString());
+        log.debug( "TLV Tree : " + sb.toString() );
     }
     
     /**
@@ -254,11 +247,11 @@
      */
     private boolean isTLVDecoded( IAsn1Container container )
     {
-        TLV current = container.getCurrentTLV();
+        TLV currentTLV = container.getCurrentTLV();
         
-        TLV parent = current.getParent();
+        TLV parent = currentTLV.getParent();
         
-        while (parent != null)
+        while ( parent != null )
         {
         	if (parent.getExpectedLength() != 0)
         	{
@@ -268,15 +261,15 @@
         	parent = parent.getParent();
         }
         
-        Value value = current.getValue();
+        Value value = currentTLV.getValue();
         
-        if ( (value != null) && (value.getData() != null) )
+        if ( ( value != null ) && ( value.getData() != null ) )
         {
-            return (current.getExpectedLength() == value.getData().length);
+            return ( currentTLV.getExpectedLength() == value.getData().length );
         } 
         else
         {
-            return current.getExpectedLength() == 0;
+            return currentTLV.getExpectedLength() == 0;
         }
     }
     
@@ -293,18 +286,20 @@
     private void treatTagEndState( IAsn1Container container )
         throws DecoderException
     {
+        TLV currentTlv = container.getCurrentTLV(); 
 
         if ( DEBUG )
         {
-            Tag tag = container.getCurrentTLV().getTag();
+            Tag tag = currentTlv.getTag();
             log.debug( tag.toString() + " has been decoded" );
         }
         
-        // Create a link between the current TLV with its parent
-        container.getCurrentTLV().setParent(container.getParentTLV());
+        // Create a link between the current TLV with its parent, if any.
+        currentTlv.setParent( container.getParentTLV() );
         
         // After having decoded a tag, we have to execute the action
         // which controls if this tag is allowed and well formed.
+        // TODO : this is totally useless.
         container.getGrammar().executeAction( container );
 
         // Switch to the next state, which is the Length decoding
@@ -327,39 +322,37 @@
     private boolean treatLengthStartState( ByteBuffer stream, IAsn1Container container )
         throws DecoderException
     {
-
         if ( stream.hasRemaining() )
         {
-
             byte octet = stream.get();
-
+    
             Length length = container.getCurrentTLV().getLength();
-
+    
             if ( ( octet & Length.LENGTH_LONG_FORM ) == 0 )
             {
-
+    
                 // We don't have a long form. The Length of the Value part is
                 // given by this byte.
                 length.setLength( octet );
                 length.setExpectedLength( 0 );
                 length.setCurrentLength( 0 );
                 length.setSize( 1 );
-
+    
                 container.setState( TLVStateEnum.LENGTH_STATE_END );
             }
             else if ( ( octet & Length.LENGTH_EXTENSION_RESERVED ) !=
                     Length.LENGTH_EXTENSION_RESERVED )
             {
-
+    
                 int expectedLength = octet & Length.SHORT_MASK;
-
+    
                 if ( expectedLength > 4 )
                 {
                     log.error( "Overflow : can't have more than 4 bytes long length" );
                     throw new DecoderException(
                         "Overflow : can't have more than 4 bytes long length" );
                 }
-
+    
                 length.setExpectedLength( expectedLength );
                 length.setCurrentLength( 0 );
                 length.setLength( 0 );
@@ -376,7 +369,6 @@
         }
         else
         {
-
             return END;
         }
     }
@@ -397,34 +389,31 @@
     private boolean treatLengthPendingState( ByteBuffer stream, IAsn1Container container )
         throws DecoderException
     {
-
-        if ( stream.hasRemaining() )
+        if (stream.hasRemaining() )
         {
-
             Length length = container.getCurrentTLV().getLength();
-
+    
             while ( length.getCurrentLength() < length.getExpectedLength() )
             {
-
+    
                 byte octet = stream.get();
-
+    
                 if ( DEBUG )
                 {
                     log.debug( "  current byte : " + StringUtils.dumpByte( octet ) );
                 }
-
+    
                 length.incCurrentLength();
                 length.incSize();
                 length.setLength( ( length.getLength() << 8 ) | (octet & 0x00FF));
             }
-
+    
             container.setState( TLVStateEnum.LENGTH_STATE_END );
-
+            
             return MORE;
         }
         else
         {
-
             return END;
         }
     }
@@ -471,7 +460,7 @@
         throws DecoderException
     {
         TLV tlv = container.getCurrentTLV();
-        Length length = tlv.getLength();
+        int length = tlv.getLength().getLength();
 
         // We will check the length here. What we must control is
         // that the enclosing constructed TLV expected length is not
@@ -480,19 +469,19 @@
         
         if ( DEBUG )
         {
-            log.debug(getParentLength(parentTLV));
+            log.debug( getParentLength( parentTLV ) );
         }
         
-        if (parentTLV == null) 
+        if ( parentTLV == null ) 
         {
             // This is the first TLV, so we can't check anything. We will
             // just store this TLV as the root of the PDU
-            tlv.setExpectedLength(length.getLength());
-            container.setParentTLV(tlv);
+            tlv.setExpectedLength( length );
+            container.setParentTLV( tlv );
             
             if ( DEBUG )
             {
-                log.debug("Root TLV[" + tlv.getLength().getLength() + "]");
+                log.debug( "Root TLV[" + length + "]" );
             }
         }
         else
@@ -502,46 +491,46 @@
             int expectedLength = parentTLV.getExpectedLength();
             int currentLength = tlv.getSize();
             
-            if (expectedLength < currentLength)
+            if ( expectedLength < currentLength )
             {
                 // The expected length is lower than the Value length of the
                 // current TLV. This is an error...
-                log.error("tlv[" + expectedLength + ", " + currentLength + "]");
-                throw new DecoderException("The current Value length is above the expected length");
+                log.error( "tlv[" + expectedLength + ", " + currentLength + "]" );
+                throw new DecoderException( "The current Value length is above the expected length" );
             }
             
-            if (expectedLength == currentLength)
+            if ( expectedLength == currentLength )
             {
-                parentTLV.setExpectedLength(0);
-
                 // deal with the particular case where expected length equal
                 // the current length, which means that the parentTLV has been
                 // completed. 
-                // We also have to check that the current TLV is a constructed
-                // one. 
+                // The parent length must be reset.
+                parentTLV.setExpectedLength( 0 );
+                tlv.setExpectedLength( length );
+
+                // Check the current length, and also check that the current TLV 
+                // is a constructed one.
                 // In this case, we have to switch from this parent TLV
                 // to the parent's parent TLV.
-                if (tlv.getTag().isConstructed())
+                if ( ( length != 0 ) && ( tlv.getTag().isConstructed() ) )
                 {
                     // It's a constructed TLV. We will set it's parent to the 
                     // parentTLV, and it will become the new parent TLV, after
-                    // having set the new expected length.
-                    tlv.setParent(parentTLV);
-                    tlv.setExpectedLength(tlv.getLength().getLength());
-                    container.setParentTLV(tlv);
+                    // having set the new expected length
+                    tlv.setParent( parentTLV ) ;
+                    container.setParentTLV( tlv );
                 }
                 else
                 {
-                    tlv.setExpectedLength(tlv.getLength().getLength());
-                    // It's over, the parent TLV has been completed.
-                    // Go back to the parent's parent TLV until we find
-                    // a tlv which is not complete.
-                    while (parentTLV != null)
+                    // We have to unstack the parentTLV until we 
+                    // find one which length is not null. It will
+                    // become the container parentTLV.
+                    while ( parentTLV != null )
                     {
                         if ( parentTLV.getExpectedLength() != 0 )
                         {
-                            // ok, we have an incomplete parent. we will
-                            // stop the recursion right here
+                            // Ok, we have an incomplete parent. we will
+                            // stop the recursion rigth here
                             break;
                         }
                         else
@@ -549,41 +538,41 @@
                             parentTLV = parentTLV.getParent();
                         }
                     }
-                    
-                    container.setParentTLV(parentTLV);
+
+                    // The parent might be null.
+                    container.setParentTLV( parentTLV ) ;
                 }
             }
             else
             {
 	            // Renew the expected Length.
-	            parentTLV.setExpectedLength(expectedLength - currentLength);
-                tlv.setExpectedLength(tlv.getLength().getLength());
+	            parentTLV.setExpectedLength( expectedLength - currentLength) ;
+                tlv.setExpectedLength( length );
 	            
-	            if (tlv.getTag().isConstructed())
+	            if ( tlv.getTag().isConstructed() )
 	            {
-	                // We have a constructed tag, so we must switch the parentTLV
-                    tlv.setParent(parentTLV);
-                    tlv.setExpectedLength(tlv.getLength().getLength());
-                    container.setParentTLV(tlv);
+	                // We have a constructed tag, so we must change the 
+                    // container parentTLV. The current container parentTLV 
+                    // will be store in the current TLV.
+                    tlv.setParent( parentTLV );
+                    tlv.setExpectedLength( length );
+                    container.setParentTLV( tlv );
 	            }
             }
-            
         }
 
         if ( DEBUG )
         {
-            log.debug( length.toString() + " has been decoded" );
+            log.debug( tlv.getLength().toString() + " has been decoded" );
         }
 
-        if ( length.getLength() == 0 )
+        if ( length == 0 )
         {
-
             // The length is 0, so we can't expect a value.
             container.setState( TLVStateEnum.TLV_STATE_DONE );
         }
         else
         {
-
             // Go ahead and decode the value part
             container.setState( TLVStateEnum.VALUE_STATE_START );
         }
@@ -606,13 +595,13 @@
     private boolean treatValueStartState( ByteBuffer stream, IAsn1Container container )
         throws DecoderException
     {
-
         TLV currentTlv = container.getCurrentTLV();
+        Value value = currentTlv.getValue();
 
         if ( currentTlv.getTag().isConstructed() )
         {
             container.setState( TLVStateEnum.TLV_STATE_DONE );
-
+            
             return MORE;
         }
         else
@@ -620,21 +609,20 @@
 
             int length  = currentTlv.getLength().getLength();
             int nbBytes = stream.remaining();
+            value.init( length );
 
             if ( nbBytes < length )
             {
-                currentTlv.getValue().init( length );
-                currentTlv.getValue().setData( stream );
+                value.setData( stream );
                 container.setState( TLVStateEnum.VALUE_STATE_PENDING );
-
+                
                 return END;
             }
             else
             {
-                currentTlv.getValue().init( length );
-                stream.get( currentTlv.getValue().getData(), 0, length );
+                stream.get( value.getData(), 0, length );
                 container.setState( TLVStateEnum.TLV_STATE_DONE );
-
+                
                 return MORE;
             }
         }
@@ -658,16 +646,17 @@
     {
 
         TLV currentTlv    = container.getCurrentTLV();
+        Value value       = currentTlv.getValue();
 
         int length        = currentTlv.getLength().getLength();
-        int currentLength = currentTlv.getValue().getCurrentLength();
+        int currentLength = value.getCurrentLength();
         int nbBytes       = stream.remaining();
 
         if ( ( currentLength + nbBytes ) < length )
         {
-            currentTlv.getValue().addData( stream );
+            value.addData( stream );
             container.setState( TLVStateEnum.VALUE_STATE_PENDING );
-
+            
             return END;
         }
         else
@@ -676,9 +665,9 @@
             int    remaining = length - currentLength;
             byte[] data      = new byte[remaining];
             stream.get( data, 0, remaining );
-            currentTlv.getValue().addData( data );
+            value.addData( data );
             container.setState( TLVStateEnum.TLV_STATE_DONE );
-
+            
             return MORE;
         }
     }
@@ -733,10 +722,8 @@
     */
     private String stateToString( int state )
     {
-
         switch ( state )
         {
-
             case TLVStateEnum.TAG_STATE_START :
                 return "TAG_STATE_START";
 
@@ -784,7 +771,7 @@
      * 
      * @throws DecoderException Thrown if anything went wrong!
      */
-    public void decode( ByteBuffer stream, IAsn1Container container ) throws org.apache.asn1.codec.DecoderException
+    public void decode( ByteBuffer stream, IAsn1Container container ) throws DecoderException
     {
 
         /* We have to deal with the current state. This is an
@@ -796,7 +783,7 @@
          * all information to track back this case, and punish the guilty !
          */
 
-        boolean hasRemaining = stream.hasRemaining();
+        // boolean hasRemaining = stream.hasRemaining();
 
         if ( DEBUG )
         {
@@ -805,6 +792,8 @@
             log.debug( ">>>------------------------------------------" );
         }
 
+        boolean hasRemaining = stream.hasRemaining();
+        
         while ( hasRemaining )
         {
 
@@ -826,7 +815,6 @@
 
             switch ( container.getState() )
             {
-
                 case TLVStateEnum.TAG_STATE_START :
                     hasRemaining = treatTagStartState( stream, container );
 
@@ -872,7 +860,7 @@
                     break;
 
                 case TLVStateEnum.VALUE_STATE_END :
-                	hasRemaining = stream.hasRemaining();
+                    hasRemaining = stream.hasRemaining();
 
                     // Nothing to do. We will never reach this state
                     break;
@@ -890,25 +878,22 @@
                         log.warn("The PDU has been fully decoded but there are still bytes in the buffer.");
                     }
                     
-                    hasRemaining = false;
+                    if ( DEBUG )
+                    {
+                        log.debug( "<<<------------------------------------------" );
+                        log.debug( "<-- Stop decoding : " + container.getCurrentTLV().toString() );
+                        log.debug( "<<<==========================================" );
+                    }
                     
-                    break;
+                    return;
             }
         }
 
         if ( DEBUG )
         {
             log.debug( "<<<------------------------------------------" );
-            
-            if ( container.getState() == TLVStateEnum.PDU_DECODED )
-            {
-                log.debug( "<-- Stop decoding : " + container.getCurrentTLV().toString() );
-            }
-            else
-            {
-                log.debug( "<-- End decoding : " + container.getCurrentTLV().toString() );
-            }
-            
+            log.debug( "  no more byte to decode in the stream");
+            log.debug( "<-- End decoding : " + container.getCurrentTLV().toString() );
             log.debug( "<<<==========================================" );
         }