Frama-c, по-видимому, позволяет выполнять циклические вычисления целых чисел без знака, в то время как предполагает, что целочисленные вычисления со знаком не будут переполняться, и это необходимо для последующего подтверждения с помощью флага -wp-rte. (Я лично использую Frama-C 20.0 Calcium.) Я хотел бы каким-то образом создать гарантию / требование, что некоторые вычисления / свойства не переполняются. Упрощенная версия проблемы, которую я пытаюсь решить:

#include <stdint.h>

struct example_struct {
  unsigned int a;
  unsigned int b;
};

/*@
  predicate valid_example_struct_one{L}(struct example_struct ex_struct) =
    ex_struct.a * ex_struct.b <= UINT_MAX;
*/

Очевидно, что приведенный выше предикат всегда верен из-за циклического перехода к беззнаковой целочисленной математике. Я хотел бы иметь возможность привести a и b к целочисленному типу, который не будет переполняться, или как-то указать, что он не может переполняться, используя другой метод. Похоже, что следующее работает:

/*@
  predicate valid_example_struct_two{L}(struct example_struct ex_struct) =
    1 <= UINT_MAX / ex_struct.a / ex_struct.b;
*/

Однако я не уверен, что приведенное выше действительно эквивалентно, поскольку оно изо всех сил пытается доказать (обратите внимание на поменяемые местами a и b):

  1 <= UINT_MAX / ex_struct.b / ex_struct.a;

И я хотел бы включить "тип" для метода Байеса, но когда я отбрасываю это, чтобы получить синтаксис в моем списке, я все равно получаю сообщение об ошибке:

1
Greenbeard 4 Май 2020 в 04:01

2 ответа

Ваш предикат

/*@
  predicate valid_example_struct_one{L}(struct example_struct ex_struct) =
    ex_struct.a * ex_struct.b <= UINT_MAX;
*/

Не является «всегда истинным из-за циклического перехода к беззнаковой целочисленной математике». Как упоминалось в руководстве по ACSL, все арифметические операции в ACSL выполняются в типе integer (или real), то есть без циклического перехода. Таким образом, это канонический способ выразить отсутствие арифметического переполнения и тот, который используется RTE и Eva при отправке связанных сигналов тревоги.

Тем не менее, RTE вполне может выдавать утверждение о переполнении без знака, но это должно быть активировано явно с помощью параметра ядра -warn-unsigned-overflow (см. руководство пользователя Frama-C , раздел 6.3. Причина, по которой этот параметр не активирован по умолчанию, заключается в том, что, в отличие, например, от подписанных переполнений, неподписанные переполнения имеют идеально определенная семантика в C.

0
Virgile 4 Май 2020 в 07:55

Хорошо, я ненавижу задавать вопросы только для того, чтобы сам на них отвечать, но я потратил немного времени на изучение документации Frama-C после того, как нашел некоторые другие вопросы, которые были интересны в Stackoverflow. Я обратил внимание на особые типы integer, real и boolean. В этом случае мою проблему можно решить, просто приведя unsigned int к integer:

/* Desired predicate: */
/*@
  predicate valid_example_struct_one{L}(struct example_struct ex_struct) =
    (integer) ex_struct.a * (integer) ex_struct.b <= (integer) UINT_MAX;
*/

/* Trivially always true predicate: */
/*@
  predicate valid_example_struct_two{L}(struct example_struct ex_struct) =
    ex_struct.a * ex_struct.b <= UINT_MAX;
*/
0
Greenbeard 4 Май 2020 в 06:07