簡體   English   中英

使用 Frama-C 和 Eva 的動態數組

[英]Dynamic array with Frama-C and Eva

https://stackoverflow.com/a/57116260/946226 中,我學會了如何驗證對緩沖區(由開始和結束指針給出)操作的函數foo是否真的只讀取它,但創建了一個具有代表性的main函數稱之為:

#include <stddef.h>

#define N 100
char test[N];

extern char *foo(char *, char *);

int main() {
  char* beg, *end;
  beg = &test[0];
  end = &test[0] + N;
  foo(beg, end);
}

但這並不能捕獲僅在緩沖區很短時才會出現的錯誤。

我嘗試了以下方法:

#include <stddef.h>
#include <stdlib.h>
#include "__fc_builtin.h"

extern char *foo(char *, char *);

int main() {
  int n = Frama_C_interval(0, 255);
  uint8_t *test = malloc(n);
  if (test != NULL) {
    for (int i=0; i<n; i++) test[i]=Frama_C_interval(0, 255);

    char* beg, *end;
    beg = &test[0];
    end = &test[0] + n;
    foo(beg, end);
  }
}

但這不起作用:

[eva:alarm] frama-main.c:14: Warning: 
  out of bounds write. assert \valid(test + i);

我可以讓它工作嗎?

正如 anol 的評論中提到的,Eva 中可用的抽象域都不能跟蹤nmalloc返回的內存塊長度之間的關系。 因此,出於所有實際目的,在這種情況下無法消除警告以進行現實生活分析。 一般來說,准備一個初始狀態很重要,它可以為整個程序中操縱的緩沖區提供精確的邊界(而內容可以保持更加抽象)。

也就是說,對於較小的實驗,並且如果您不介意浪費(相當多)CPU 周期,則可以通過基本上指示 Eva 分別考慮每個可能的長度來作弊。 這是通過一些注釋和命令行選項完成的(僅限 Frama-C 19.0 Potassium)

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "__fc_builtin.h"

extern char *foo(char *, char *);

int main() {
  int n = Frama_C_interval(0, 255);
  //@ split n;
  uint8_t *test = malloc(n);
  if (test != NULL) {
    //@ loop unroll n;
    for (int i=0; i<n; i++) {
      Frama_C_show_each_test(n, i, test);
      test[i]=Frama_C_interval(0, 255);
    }
    char* beg, *end;
    beg = &test[0];
    end = &test[0] + n;
    foo(beg, end);
  }
}

啟動 Frame-C

  frama-c -eva file.c \
          -eva-precision 7 \
          -eva-split-limit 256 \
          -eva-builtin malloc:Frama_C_malloc_fresh

在代碼中, //@ split n表示此時Eva 應該單獨考慮n每個可能值。 它與-eva-split-limit 256一起使用(默認情況下,如果表達式可以有 100 個以上的值,則 Eva 不會拆分)。 //@ loop unroll n要求展開循環n ,而不是合並的所有步驟,結果倍。

對於其他命令行選項, -eva-precision 7將控制 Eva 精度的各種參數設置為合理的值。 它從0 (比默認值更不精確)到11 (最大精度 - 不要在超過十幾行的任何內容上嘗試)。 -eva-builtin malloc:Frama_C_malloc_fresh指示 Eva 為它遇到的任何malloc調用創建一個新的基地址。 否則,您將獲得所有長度的單個鹼基,從而破壞了首先在n上分裂的目的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM