예제 #1
0
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)
예제 #2
0
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]
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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))
예제 #6
0
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)'))])
    ]
예제 #7
0
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)])
예제 #8
0
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)')))])
예제 #9
0
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))
예제 #10
0
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))')))
            ])
    ]
예제 #11
0
                                '(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: