示例#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 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)'))])
    ]
示例#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 create_verify_message_procedure(self, message: Message) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify_Message", [InOutParameter(["Ctx"], "Context")])

        loop_invariant = And(
            Call("Has_Buffer", [Variable("Ctx")]),
            *common.context_invariant(message, loop_entry=True),
        )

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(
                            Call(
                                self.prefix * message.identifier *
                                "Has_Buffer",
                                [Variable("Ctx")],
                            )),
                        Postcondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                *common.context_invariant(message),
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [],
                    [
                        ForIn(
                            "F",
                            Variable("Field"),
                            [
                                PragmaStatement("Loop_Invariant",
                                                [loop_invariant]),
                                CallStatement("Verify",
                                              [Variable("Ctx"),
                                               Variable("F")]),
                            ],
                        )
                    ],
                )
            ],
        )
示例#5
0
 def initialize_field_statements(self, message: Message, field: Field) -> Sequence[Statement]:
     return [
         CallStatement("Reset_Dependent_Fields", [Name("Ctx"), Name(field.affixed_name)],),
         Assignment(
             "Ctx",
             Aggregate(
                 Selected("Ctx", "Buffer_First"),
                 Selected("Ctx", "Buffer_Last"),
                 Selected("Ctx", "First"),
                 Name("Last"),
                 Selected("Ctx", "Buffer"),
                 Selected("Ctx", "Cursors"),
             ),
         ),
         # WORKAROUND:
         # Limitation of GNAT Community 2019 / SPARK Pro 20.0
         # Provability of predicate is increased by adding part of
         # predicate as assert
         PragmaStatement(
             "Assert", [str(self.message_structure_invariant(message, prefix=True))],
         ),
         Assignment(
             Indexed(Selected("Ctx", "Cursors"), Name(field.affixed_name)),
             NamedAggregate(
                 ("State", Name("S_Structural_Valid")),
                 ("First", Name("First")),
                 ("Last", Name("Last")),
                 ("Value", NamedAggregate(("Fld", Name(field.affixed_name))),),
                 (
                     "Predecessor",
                     Selected(
                         Indexed(Selected("Ctx", "Cursors"), Name(field.affixed_name),),
                         "Predecessor",
                     ),
                 ),
             ),
         ),
         Assignment(
             Indexed(
                 Selected("Ctx", "Cursors"),
                 Call("Successor", [Name("Ctx"), Name(field.affixed_name)]),
             ),
             NamedAggregate(
                 ("State", Name("S_Invalid")), ("Predecessor", Name(field.affixed_name)),
             ),
         ),
     ]
示例#6
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))')))
            ])
    ]
示例#7
0
    def create_verify_procedure(self, message: Message,
                                context_invariant: Sequence[Expr]) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify",
            [InOutParameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        valid_field_condition = And(
            Call(
                "Valid_Value",
                [Variable("Value")],
            ),
            Call(
                "Field_Condition",
                [
                    Variable("Ctx"),
                    Variable("Value"),
                    *([
                        Call(
                            "Field_Length",
                            [Variable("Ctx"), Variable("Fld")])
                    ] if common.length_dependent_condition(message) else []),
                ],
            ),
        )

        set_cursors_statements = [
            IfStatement(
                [(
                    Call("Composite_Field", [Variable("Fld")]),
                    [
                        Assignment(
                            Indexed(Variable("Ctx.Cursors"), Variable("Fld")),
                            NamedAggregate(
                                ("State", Variable("S_Structural_Valid")),
                                (
                                    "First",
                                    Call("Field_First",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                                (
                                    "Last",
                                    Call("Field_Last",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                ),
                                ("Value", Variable("Value")),
                                (
                                    "Predecessor",
                                    Selected(
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable("Fld")),
                                        "Predecessor",
                                    ),
                                ),
                            ),
                        )
                    ],
                )],
                [
                    Assignment(
                        Indexed(Variable("Ctx.Cursors"), Variable("Fld")),
                        NamedAggregate(
                            ("State", Variable("S_Valid")),
                            ("First",
                             Call("Field_First",
                                  [Variable("Ctx"),
                                   Variable("Fld")])),
                            ("Last",
                             Call("Field_Last",
                                  [Variable("Ctx"),
                                   Variable("Fld")])),
                            ("Value", Variable("Value")),
                            (
                                "Predecessor",
                                Selected(
                                    Indexed(Variable("Ctx.Cursors"),
                                            Variable("Fld")), "Predecessor"),
                            ),
                        ),
                    )
                ],
            ),
            # WORKAROUND:
            # Limitation of GNAT Community 2019 / SPARK Pro 20.0
            # Provability of predicate is increased by adding part of
            # predicate as assert
            PragmaStatement("Assert", [
                str(common.message_structure_invariant(message, self.prefix))
            ]),
            # WORKAROUND:
            # Limitation of GNAT Community 2019 / SPARK Pro 20.0
            # Provability of predicate is increased by splitting
            # assignment in multiple statements
            IfStatement([(
                Equal(Variable("Fld"), Variable(f.affixed_name)),
                [
                    Assignment(
                        Indexed(
                            Variable("Ctx.Cursors"),
                            Call("Successor",
                                 [Variable("Ctx"),
                                  Variable("Fld")]),
                        ),
                        NamedAggregate(
                            ("State", Variable("S_Invalid")),
                            ("Predecessor", Variable("Fld")),
                        ),
                    )
                ],
            ) for f in message.fields]),
        ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Postcondition(
                            And(
                                Equal(
                                    Call("Has_Buffer", [Variable("Ctx")]),
                                    Old(Call("Has_Buffer", [Variable("Ctx")])),
                                ),
                                *context_invariant,
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [ObjectDeclaration(["Value"], "Field_Dependent_Value")],
                    [
                        IfStatement([(
                            AndThen(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                Call(
                                    "Invalid",
                                    [
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable("Fld"))
                                    ],
                                ),
                                Call("Valid_Predecessor",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                                Call("Path_Condition",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                            ),
                            [
                                IfStatement(
                                    [(
                                        Call(
                                            "Sufficient_Buffer_Length",
                                            [Variable("Ctx"),
                                             Variable("Fld")],
                                        ),
                                        [
                                            Assignment(
                                                "Value",
                                                Call(
                                                    "Get_Field_Value",
                                                    [
                                                        Variable("Ctx"),
                                                        Variable("Fld")
                                                    ],
                                                ),
                                            ),
                                            IfStatement(
                                                [(
                                                    valid_field_condition,
                                                    set_cursors_statements,
                                                )],
                                                [
                                                    Assignment(
                                                        Indexed(
                                                            Variable(
                                                                "Ctx.Cursors"),
                                                            Variable("Fld"),
                                                        ),
                                                        NamedAggregate(
                                                            (
                                                                "State",
                                                                Variable(
                                                                    "S_Invalid"
                                                                ),
                                                            ),
                                                            (
                                                                "Predecessor",
                                                                Variable(
                                                                    FINAL.
                                                                    affixed_name
                                                                ),
                                                            ),
                                                        ),
                                                    )
                                                ],
                                            ),
                                        ],
                                    )],
                                    [
                                        Assignment(
                                            Indexed(Variable("Ctx.Cursors"),
                                                    Variable("Fld")),
                                            NamedAggregate(
                                                ("State",
                                                 Variable("S_Incomplete")),
                                                (
                                                    "Predecessor",
                                                    Variable(
                                                        FINAL.affixed_name),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
示例#8
0
    def create_verify_procedure(
        self,
        message: Message,
        scalar_fields: Mapping[Field, Scalar],
        composite_fields: Sequence[Field],
    ) -> UnitPart:
        specification = ProcedureSpecification(
            "Verify",
            [InOutParameter(["Ctx"], "Context"),
             Parameter(["Fld"], "Field")])

        valid_field_condition = AndThen(
            Call(
                "Valid_Value",
                [Variable("Fld"), Variable("Value")],
            ),
            Call(
                "Field_Condition",
                [
                    Variable("Ctx"),
                    Variable("Fld"),
                    *([Variable("Value")] if
                      common.has_value_dependent_condition(message) else []),
                    *([
                        Slice(
                            Variable("Ctx.Buffer.all"),
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Call("Field_First",
                                         [Variable("Ctx"),
                                          Variable("Fld")])
                                ],
                            ),
                            Call(
                                const.TYPES_TO_INDEX,
                                [
                                    Call("Field_Last",
                                         [Variable("Ctx"),
                                          Variable("Fld")])
                                ],
                            ),
                        )
                    ] if common.has_aggregate_dependent_condition(message) else
                      []),
                    *([Call("Field_Size",
                            [Variable("Ctx"), Variable("Fld")])]
                      if common.has_size_dependent_condition(message) else []),
                ],
            ),
        )

        last = Mul(
            Div(
                Add(
                    Call("Field_Last",
                         [Variable("Ctx"), Variable("Fld")]),
                    Size(const.TYPES_BYTE),
                    -Number(1),
                ),
                Size(const.TYPES_BYTE),
            ),
            Size(const.TYPES_BYTE),
        )
        set_cursors_statements = [
            *([
                PragmaStatement(
                    "Assert",
                    [
                        If([(
                            Or(*[
                                Equal(Variable("Fld"), Variable(
                                    f.affixed_name))
                                for f in message.direct_predecessors(FINAL)
                            ]),
                            Equal(
                                Mod(
                                    Call("Field_Last",
                                         [Variable("Ctx"),
                                          Variable("Fld")]),
                                    Size(const.TYPES_BYTE),
                                ),
                                Number(0),
                            ),
                        )])
                    ],
                )
            ] if len(message.fields) > 1 else []),
            # Improve provability of context predicate
            PragmaStatement(
                "Assert",
                [Equal(Mod(last, Size(const.TYPES_BYTE)), Number(0))]),
            Assignment(Variable("Ctx.Verified_Last"), last),
            PragmaStatement(
                "Assert",
                [
                    LessEqual(
                        Call("Field_Last", [Variable("Ctx"),
                                            Variable("Fld")]),
                        Variable("Ctx.Verified_Last"),
                    )
                ],
            ),
            IfStatement(
                [(
                    Call("Composite_Field", [Variable("Fld")]),
                    [set_context_cursor_composite_field("Fld")],
                )],
                [set_context_cursor_scalar()],
            ) if scalar_fields and composite_fields else
            set_context_cursor_scalar()
            if scalar_fields and not composite_fields else
            set_context_cursor_composite_field("Fld"),
            *([
                # https://github.com/Componolit/RecordFlux/issues/664
                # The provability of the context predicate is increased by splitting the
                # assignment into multiple statements.
                Assignment(
                    Indexed(
                        Variable("Ctx.Cursors"),
                        Call(
                            "Successor",
                            [Variable("Ctx"), Variable("Fld")],
                        ),
                    ),
                    NamedAggregate(
                        ("State", Variable("S_Invalid")),
                        ("Predecessor", Variable("Fld")),
                    ),
                )
            ] if len(message.fields) > 1 else []),
        ]

        return UnitPart(
            [
                SubprogramDeclaration(
                    specification,
                    [
                        Precondition(
                            Call(
                                self.prefix * message.identifier *
                                "Has_Buffer",
                                [Variable("Ctx")],
                            )),
                        Postcondition(
                            And(
                                Call("Has_Buffer", [Variable("Ctx")]),
                                *common.context_invariant(message),
                            )),
                    ],
                )
            ],
            [
                SubprogramBody(
                    specification,
                    [ObjectDeclaration(["Value"], const.TYPES_BASE_INT)],
                    [
                        IfStatement([(
                            AndThen(
                                Call(
                                    "Invalid",
                                    [
                                        Indexed(Variable("Ctx.Cursors"),
                                                Variable("Fld"))
                                    ],
                                ),
                                Call("Valid_Predecessor",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                                Call("Path_Condition",
                                     [Variable("Ctx"),
                                      Variable("Fld")]),
                            ),
                            [
                                IfStatement(
                                    [(
                                        Call(
                                            "Sufficient_Buffer_Length",
                                            [Variable("Ctx"),
                                             Variable("Fld")],
                                        ),
                                        [
                                            Assignment(
                                                "Value",
                                                If(
                                                    [(
                                                        Call(
                                                            "Composite_Field",
                                                            [
                                                                Variable(
                                                                    "Fld"),
                                                            ],
                                                        ),
                                                        Number(0),
                                                    )],
                                                    Call(
                                                        "Get",
                                                        [
                                                            Variable("Ctx"),
                                                            Variable("Fld"),
                                                        ],
                                                    ),
                                                ) if scalar_fields
                                                and composite_fields else Call(
                                                    "Get",
                                                    [
                                                        Variable("Ctx"),
                                                        Variable("Fld"),
                                                    ],
                                                ) if scalar_fields else
                                                Number(0),
                                            ),
                                            IfStatement(
                                                [(
                                                    valid_field_condition,
                                                    set_cursors_statements,
                                                )],
                                                [
                                                    Assignment(
                                                        Indexed(
                                                            Variable(
                                                                "Ctx.Cursors"),
                                                            Variable("Fld"),
                                                        ),
                                                        NamedAggregate(
                                                            (
                                                                "State",
                                                                Variable(
                                                                    "S_Invalid"
                                                                ),
                                                            ),
                                                            (
                                                                "Predecessor",
                                                                Variable(
                                                                    FINAL.
                                                                    affixed_name,
                                                                ),
                                                            ),
                                                        ),
                                                    )
                                                ],
                                            ),
                                        ],
                                    )],
                                    [
                                        Assignment(
                                            Indexed(Variable("Ctx.Cursors"),
                                                    Variable("Fld")),
                                            NamedAggregate(
                                                ("State",
                                                 Variable("S_Incomplete")),
                                                (
                                                    "Predecessor",
                                                    Variable(
                                                        FINAL.affixed_name),
                                                ),
                                            ),
                                        )
                                    ],
                                )
                            ],
                        )], )
                    ],
                )
            ],
        )
示例#9
0
def initialize_field_statements(
    field: model.Field, reset_written_last: bool = False
) -> Sequence[Statement]:
    return [
        CallStatement(
            "Reset_Dependent_Fields",
            [Variable("Ctx"), Variable(field.affixed_name)],
        ),
        # https://github.com/Componolit/RecordFlux/issues/868
        PragmaStatement(
            "Warnings",
            [
                Variable("Off"),
                String("attribute Update is an obsolescent feature"),
            ],
        ),
        Assignment(
            "Ctx",
            Update(
                "Ctx",
                ("Verified_Last", Variable("Last")),
                (
                    "Written_Last",
                    Variable("Last")
                    if reset_written_last
                    else Max(
                        const.TYPES_BIT_LENGTH,
                        Variable("Ctx.Written_Last"),
                        Variable("Last"),
                    ),
                ),
            ),
        ),
        PragmaStatement(
            "Warnings",
            [
                Variable("On"),
                String("attribute Update is an obsolescent feature"),
            ],
        ),
        Assignment(
            Indexed(Variable("Ctx.Cursors"), Variable(field.affixed_name)),
            NamedAggregate(
                ("State", Variable("S_Structural_Valid")),
                ("First", Variable("First")),
                ("Last", Variable("Last")),
                ("Value", Number(0)),
                (
                    "Predecessor",
                    Selected(
                        Indexed(
                            Variable("Ctx.Cursors"),
                            Variable(field.affixed_name),
                        ),
                        "Predecessor",
                    ),
                ),
            ),
        ),
        Assignment(
            Indexed(
                Variable("Ctx.Cursors"),
                Call(
                    "Successor",
                    [Variable("Ctx"), Variable(field.affixed_name)],
                ),
            ),
            NamedAggregate(
                ("State", Variable("S_Invalid")),
                ("Predecessor", Variable(field.affixed_name)),
            ),
        ),
    ]