• David Howells's avatar
    ASN.1: Fix actions on CHOICE elements with IMPLICIT tags · 3f3af97d
    David Howells authored
    In an ASN.1 description where there is a CHOICE construct that contains
    elements with IMPLICIT tags that refer to constructed types, actions to be
    taken on those elements should be conditional on the corresponding element
    actually being matched.  Currently, however, such actions are performed
    unconditionally in the middle of processing the CHOICE.
    
    For example, look at elements 'b' and 'e' here:
    
    	A ::= SEQUENCE {
    			CHOICE {
    			b [0] IMPLICIT B ({ do_XXXXXXXXXXXX_b }),
    			c [1] EXPLICIT C ({ do_XXXXXXXXXXXX_c }),
    			d [2] EXPLICIT B ({ do_XXXXXXXXXXXX_d }),
    			e [3] IMPLICIT C ({ do_XXXXXXXXXXXX_e }),
    			f [4] IMPLICIT INTEGER ({ do_XXXXXXXXXXXX_f })
    			}
    		} ({ do_XXXXXXXXXXXX_A })
    
    	B ::= SET OF OBJECT IDENTIFIER ({ do_XXXXXXXXXXXX_oid })
    
    	C ::= SET OF INTEGER ({ do_XXXXXXXXXXXX_int })
    
    They each have an action (do_XXXXXXXXXXXX_b and do_XXXXXXXXXXXX_e) that
    should only be processed if that element is matched.
    
    The problem is that there's no easy place to hang the action off in the
    subclause (type B for element 'b' and type C for element 'e') because
    subclause opcode sequences can be shared.
    
    To fix this, introduce a conditional action opcode(ASN1_OP_MAYBE_ACT) that
    the decoder only processes if the preceding match was successful.  This can
    be seen in an excerpt from the output of the fixed ASN.1 compiler for the
    above ASN.1 description:
    
    	[  13] =  ASN1_OP_COND_MATCH_JUMP_OR_SKIP,		// e
    	[  14] =  _tagn(CONT, CONS,  3),
    	[  15] =  _jump_target(45),		// --> C
    	[  16] =  ASN1_OP_MAYBE_ACT,
    	[  17] =  _action(ACT_do_XXXXXXXXXXXX_e),
    
    In this, if the op at [13] is matched (ie. element 'e' above) then the
    action at [16] will be performed.  However, if the op at [13] doesn't match
    or is skipped because it is conditional and some previous op matched, then
    the action at [16] will be ignored.
    
    Note that to make this work in the decoder, the ASN1_OP_RETURN op must set
    the flag to indicate that a match happened.  This is necessary because the
    _jump_target() seen above introduces a subclause (in this case an object of
    type 'C') which is likely to alter the flag.  Setting the flag here is okay
    because to process a subclause, a match must have happened and caused a
    jump.
    
    This cannot be tested with the code as it stands, but rather affects future
    code.
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Reviewed-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
    3f3af97d
asn1_decoder.c 12.8 KB