def contains_function(name: str, pdu: str, field: str, sdu: str, condition: LogExpr) -> Subprogram: success_statements: List[Statement] = [ReturnStatement(TRUE)] aspects: List[Aspect] = [ Precondition( And(LogCall(f'{pdu}.Is_Contained (Buffer)'), LogCall(f'{pdu}.Is_Valid (Buffer)'))) ] if sdu != 'null': success_statements.insert( 0, PragmaStatement('Assume', [( f'{sdu}.Is_Contained (Buffer ({pdu}.Get_{field}_First (Buffer)' f' .. {pdu}.Get_{field}_Last (Buffer)))')])) aspects.append( Postcondition( IfExpression([ (LogCall(f'{name}\'Result'), LogCall((f'{sdu}.Is_Contained (Buffer (' f'{pdu}.Get_{field}_First (Buffer)' f' .. {pdu}.Get_{field}_Last (Buffer)))'))) ]))) return Function(name, 'Boolean', [('Buffer', 'Types.Bytes')], [], [ IfStatement([(condition, success_statements)]), ReturnStatement(FALSE) ], aspects)
def enumeration_functions(enum: Enumeration) -> List[Subprogram]: common_precondition = And( Less(Value('Offset'), Number(8)), Equal( Length('Buffer'), Add( Div(Add(Size(enum.base_name), Value('Offset'), Number(-1)), Number(8)), Number(1)))) control_expression = LogCall( f'Convert_To_{enum.base_name} (Buffer, Offset)') validation_expression: Expr if enum.always_valid: validation_expression = Value('True') else: validation_cases: List[Tuple[Expr, Expr]] = [] validation_cases.extend( (value, Value('True')) for value in enum.literals.values()) validation_cases.append((Value('others'), Value('False'))) validation_expression = CaseExpression(control_expression, validation_cases) validation_function = ExpressionFunction( f'Valid_{enum.name}', 'Boolean', [('Buffer', 'Types.Bytes'), ('Offset', 'Natural')], validation_expression, [Precondition(common_precondition)]) function_name = f'Convert_To_{enum.name}' parameters = [('Buffer', 'Types.Bytes'), ('Offset', 'Natural')] precondition = Precondition( And(common_precondition, LogCall(f'Valid_{enum.name} (Buffer, Offset)'))) conversion_cases: List[Tuple[Expr, Expr]] = [] conversion_function: Subprogram if enum.always_valid: conversion_cases.extend((value, Aggregate(Value('True'), Value(key))) for key, value in enum.literals.items()) conversion_cases.append( (Value('others'), Aggregate(Value('False'), Value('Raw')))) conversion_function = Function( function_name, enum.name, parameters, [Declaration('Raw', enum.base_name, control_expression)], [ReturnStatement(CaseExpression(Value('Raw'), conversion_cases))], [precondition]) else: conversion_cases.extend( (value, Value(key)) for key, value in enum.literals.items()) conversion_cases.append( (Value('others'), LogCall(f'Unreachable_{enum.name}'))) conversion_function = ExpressionFunction( function_name, enum.name, parameters, CaseExpression(control_expression, conversion_cases), [precondition]) return [validation_function, conversion_function]
def field_accessor_functions(field: Field, package_name: str) -> List[Subprogram]: precondition = Precondition( And(COMMON_PRECONDITION, LogCall(f'Valid_{field.name} (Buffer)'))) functions: List[Subprogram] = [] if isinstance(field.type, Array): for attribute in ['First', 'Last']: functions.append( ExpressionFunction( f'Get_{field.name}_{attribute}', 'Types.Index_Type', [('Buffer', 'Types.Bytes')], IfExpression([( LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'), LogCall( f'Get_{field.name}_{variant_id}_{attribute} (Buffer)' )) for variant_id in field.variants], 'Unreachable_Types_Index_Type'), [precondition])) body: List[Statement] = [ Assignment('First', MathCall(f'Get_{field.name}_First (Buffer)')), Assignment('Last', MathCall(f'Get_{field.name}_Last (Buffer)')) ] postcondition = Postcondition( And( Equal(Value('First'), MathCall(f'Get_{field.name}_First (Buffer)')), Equal(Value('Last'), MathCall(f'Get_{field.name}_Last (Buffer)')))) if 'Payload' not in field.type.name: predicate = f'{package_name}.{field.type.name}.Is_Contained (Buffer (First .. Last))' body.append(PragmaStatement('Assume', [predicate])) postcondition.expr = And(postcondition.expr, LogCall(predicate)) functions.append( Procedure(f'Get_{field.name}', [('Buffer', 'Types.Bytes'), ('First', 'out Types.Index_Type'), ('Last', 'out Types.Index_Type')], [], body, [precondition, postcondition])) else: functions.append( ExpressionFunction( f'Get_{field.name}', field.type.name, [('Buffer', 'Types.Bytes')], IfExpression( [(LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'), MathCall(f'Get_{field.name}_{variant_id} (Buffer)')) for variant_id in field.variants], f'Unreachable_{field.type.name}'), [precondition])) return functions
def variant_accessor_functions(field: Field, variant_id: str, variant: Variant) -> List[Subprogram]: first_byte, last_byte, offset = field_location(field.name, variant_id, variant) name = f'Get_{field.name}_{variant_id}' precondition = Precondition( And(COMMON_PRECONDITION, LogCall(f'Valid_{field.name}_{variant_id} (Buffer)'))) functions: List[Subprogram] = [] if isinstance(field.type, Array): functions.append( ExpressionFunction(f'{name}_First', 'Types.Index_Type', [('Buffer', 'Types.Bytes')], first_byte, [precondition])) functions.append( ExpressionFunction(f'{name}_Last', 'Types.Index_Type', [('Buffer', 'Types.Bytes')], last_byte, [precondition])) else: functions.append( ExpressionFunction( name, field.type.name, [('Buffer', 'Types.Bytes')], Convert( field.type.name if field.type.constraints == TRUE else field.type.base_name, 'Buffer', first_byte, last_byte, offset), [precondition])) return functions
def valid_variants(field: Field) -> Iterator[LogExpr]: for variant_id, variant in field.variants.items(): expression: LogExpr = LogCall( f'Valid_{field.name}_{variant_id} (Buffer)') if field.condition is not TRUE: expression = And(expression, field.condition) yield expression.simplified(variant.facts).simplified( value_to_call_facts([(field.name, variant_id)] + variant.previous))
def contain_functions() -> List[Subprogram]: return [ ExpressionFunction('Is_Contained', 'Boolean', [('Buffer', 'Types.Bytes')], aspects=[Ghost(), Import()]), Procedure('Label', [('Buffer', 'Types.Bytes')], [], [PragmaStatement('Assume', ['Is_Contained (Buffer)'])], aspects=[Postcondition(LogCall('Is_Contained (Buffer)'))]) ]
def variant_validation_function(field: Field, variant_id: str, variant: Variant) -> Subprogram: type_constraints: LogExpr = TRUE if field.type.constraints != TRUE or isinstance(field.type, Enumeration): first_byte, last_byte, offset = field_location(field.name, variant_id, variant) if field.type.constraints != TRUE: convert = Convert(field.type.base_name, 'Buffer', first_byte, last_byte, offset) type_constraints = field.type.constraints.simplified( {Value(field.type.name): convert}) if isinstance(field.type, Enumeration): type_constraints = And( type_constraints, LogCall((f'Valid_{field.type.name} (Buffer ({first_byte}' f' .. {last_byte}), {offset})'))) value_to_call = value_to_call_facts([(field.name, variant_id)] + variant.previous) return ExpressionFunction( f'Valid_{field.name}_{variant_id}', 'Boolean', [('Buffer', 'Types.Bytes')], And( LogCall( f'Valid_{variant.previous[-1][0]}_{variant.previous[-1][1]} (Buffer)' ) if variant.previous else TRUE, And( And( buffer_constraints(variant.facts[Last( field.name)].to_bytes()).simplified(value_to_call), variant.condition.simplified( variant.facts).simplified(value_to_call)), type_constraints)).simplified(), [Precondition(COMMON_PRECONDITION)])
def message_length_function(variants: List[Variant]) -> Subprogram: condition_expressions: List[Tuple[LogExpr, Expr]] = [] for variant in variants: condition = variant_condition(variant) length = Add( Last(variant.previous[-1][0]), -First(variant.previous[0][0]), Number(1)).simplified(variant.facts).simplified( value_to_call_facts(variant.previous)).to_bytes().simplified() condition_expressions.append((condition, length)) return ExpressionFunction( 'Message_Length', 'Types.Length_Type', [('Buffer', 'Types.Bytes')], IfExpression(condition_expressions, 'Unreachable_Types_Length_Type'), [Precondition(And(COMMON_PRECONDITION, LogCall('Is_Valid (Buffer)')))])
def variant_condition(variant: Variant) -> LogExpr: field_name, variant_id = variant.previous[-1] return And(LogCall(f'Valid_{field_name}_{variant_id} (Buffer)'), variant.condition).simplified(variant.facts).simplified( value_to_call_facts(variant.previous))
def array_functions(array: Array, package: str) -> List[Subprogram]: common_precondition = LogCall(f'Is_Contained (Buffer)') return [ Function('Valid_First', 'Boolean', [('Buffer', 'Types.Bytes')], [], [ ReturnStatement( LogCall('Valid_Next (Buffer, Offset_Type (Buffer\'First))')) ], [Precondition(common_precondition)]), Procedure('Get_First', [ ('Buffer', 'Types.Bytes'), ('Offset', 'out Offset_Type'), ('First', 'out Types.Index_Type'), ('Last', 'out Types.Index_Type') ], [], [ Assignment('Offset', Value('Offset_Type (Buffer\'First)')), CallStatement('Get_Next', ['Buffer', 'Offset', 'First', 'Last']) ], [ Precondition( And(common_precondition, LogCall('Valid_First (Buffer)'))), Postcondition( And( And(GreaterEqual(Value('First'), First('Buffer')), LessEqual(Value('Last'), Last('Buffer'))), LogCall(f'{package}.{array.element_type}.Is_Contained ' '(Buffer (First .. Last))'))) ]), Function('Valid_Next', 'Boolean', [ ('Buffer', 'Types.Bytes'), ('Offset', 'Offset_Type') ], [], [ PragmaStatement('Assume', [ (f'{package}.{array.element_type}.Is_Contained ' '(Buffer (Types.Index_Type (Offset) .. Buffer\'Last))') ]), ReturnStatement( LogCall( f'{package}.{array.element_type}.Is_Valid ' '(Buffer (Types.Index_Type (Offset) .. Buffer\'Last))')) ], [Precondition(common_precondition)]), Procedure( 'Get_Next', [('Buffer', 'Types.Bytes'), ('Offset', 'in out Offset_Type'), ('First', 'out Types.Index_Type'), ('Last', 'out Types.Index_Type')], [], [ Assignment('First', Value('Types.Index_Type (Offset)')), Assignment( 'Last', Add( Value('First'), Cast( 'Types.Length_Type', MathCall(f'{package}.{array.element_type}.' 'Message_Length (Buffer (First ' '.. Buffer\'Last))')), Number(-1))), Assignment('Offset', Value('Offset_Type (Last + 1)')), PragmaStatement( 'Assume', [(f'{package}.{array.element_type}.Is_Contained ' '(Buffer (First .. Last))')]) ], [ Precondition( And(common_precondition, LogCall('Valid_Next (Buffer, Offset)'))), Postcondition( And( And(GreaterEqual(Value('First'), First('Buffer')), LessEqual(Value('Last'), Last('Buffer'))), LogCall(f'{package}.{array.element_type}.Is_Contained ' '(Buffer (First .. Last))'))) ]) ]
'(Buffer (First .. Last))')]) ], [ Precondition( And(common_precondition, LogCall('Valid_Next (Buffer, Offset)'))), Postcondition( And( And(GreaterEqual(Value('First'), First('Buffer')), LessEqual(Value('Last'), Last('Buffer'))), LogCall(f'{package}.{array.element_type}.Is_Contained ' '(Buffer (First .. Last))'))) ]) ] COMMON_PRECONDITION = LogCall('Is_Contained (Buffer)') def contain_functions() -> List[Subprogram]: return [ ExpressionFunction('Is_Contained', 'Boolean', [('Buffer', 'Types.Bytes')], aspects=[Ghost(), Import()]), Procedure('Label', [('Buffer', 'Types.Bytes')], [], [PragmaStatement('Assume', ['Is_Contained (Buffer)'])], aspects=[Postcondition(LogCall('Is_Contained (Buffer)'))]) ] def variant_validation_function(field: Field, variant_id: str, variant: Variant) -> Subprogram: