- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想用 Frama-c 和 WP 插件来表示,下面编写的 stringCompare 函数充当“它应该”的作用 - 即:给定相同的输入字符串,该函数返回 0 并且结果不同于 0如果字符串不相同。我已经注释了如下所示的相关函数,并希望能够证明 WP 生成的未经证实的目标,这怎么做?
我通过尝试运行带有注释的插件获得的输出可以在代码下方看到
#include <string.h>
#include <stdio.h>
/*@
requires validPointers: \valid_read(s1) && \valid_read(s2) ;
requires validLengthS1: 100 >= strlen(s1) >= 0;
requires validLengthS2: 100 >= strlen(s2) >= 0;
assigns \nothing ;
allocates \nothing ;
frees \nothing ;
behavior allEqual:
assumes \forall integer k; 0 <= k < n ==> s1[k] == s2[k];
ensures \result == 0;
behavior SomeDifferent:
assumes \exists integer k; 0 <= k < n ==> s1[k] != s2[k];
ensures \result != 0;
disjoint behaviors;
complete behaviors;
*/
int stringCompare(const char* s1, const char* s2, int n) {
if (s1 == s2)
return 0;
int i = 0;
/*@ assert \valid_read(s1) ; */
/*@ assert \valid_read(s2) ;*/
/*@ loop invariant 0 <= i;
loop assigns i , s1, s2; */
while (*s1 == *(s2++))
{
/*@ assert i <= 2147483647 ; */
++i;
if (*(s1++) == '\0')
return 0;
}
return *(unsigned char*)s1 - *(unsigned char*)(--s2);
}
/*@ assigns \nothing ;
ensures rightResult: \result == strlen(\old(str));
ensures rightEndCharacter: str[\result] == '\0' ; */
int stringLength(const char* str) {
int result = 0;
/*@ loop assigns result ;
loop invariant 0 <= result ; */
while (str[result++] != '\0');
return --result;
}
/*@ assigns \nothing ;
ensures \result == 0 ;*/
int main(void) {
const char* hello = "hello";
const char* helli = "helli";
/*@ assert \valid_read(hello) && \valid_read(helli) ; */
stringCompare(hello, helli, 5);
return 0;
}
WP 正在使用以下命令运行:'frama-c -wp -wp-model "Typed+var+int+real"-wp-timeout 20 strcmp.c'
[wp] Warning: Missing RTE guards
[wp] strcmp.c:48: Warning:
Cast with incompatible pointers types (source: sint8*) (target: uint8*)
[wp] strcmp.c:48: Warning:
Cast with incompatible pointers types (source: sint8*) (target: uint8*)
[wp] 49 goals scheduled
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_requires_validLengthS1 : Timeout (Qed:2ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_requires_validLengthS2 : Timeout (Qed:2ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_2_requires_validLengthS1 : Timeout (Qed:4ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_2_requires_validLengthS2 : Timeout (Qed:3ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_3_requires_validLengthS1 : Timeout (Qed:8ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_3_requires_validLengthS2 : Timeout (Qed:8ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_4_requires_validLengthS1 : Timeout (Qed:11ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_main_call_stringCompare_4_requires_validLengthS2 : Timeout (Qed:12ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_stringCompare_disjoint_SomeDifferent_allEqual : Timeout (Qed:3ms) (20s)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_stringCompare_allEqual_ensures : Timeout (Qed:15ms) (20s) (Stronger, 2 warnings)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_stringCompare_SomeDifferent_ensures : Timeout (Qed:14ms) (20s) (Stronger, 2 warnings)
[wp] [Alt-Ergo 2.2.0] Goal typed_real_stringLength_ensures_rightResult : Timeout (Qed:5ms) (20s)
[wp] Proved goals: 37 / 49
Qed: 30 (1ms-3ms-11ms)
Alt-Ergo 2.2.0: 7 (8ms-43ms-126ms) (464) (interrupted: 12)
最佳答案
这里有很多要点。首先,我想说的是,当遇到验证问题时,尝试使用内存模型可能不是第一件事(特别是,由于您没有使用浮点运算,+real
组件完全没用)。因此,我建议删除 -wp-model
从整个等式来看,默认选择通常就足够了。另一方面,添加 -wp-rte
还检查潜在的运行时错误可能很有趣。
当您指定 \valid_read(s1)
时,您是说您可以访问 s1[0]
, 但没有别的。如果要讲几个内存单元的有效性,可以用\valid_read(s1 + (0 .. n))
,或者,对于以空字符结尾的 C 字符串,\valid_string(s1)
.
您在 stringCompare
的两种行为中都采用了假设条款不正确:我们只是在寻找差异,直到 strlen(s1)
(包括),直到 n
(顺便说一句,这是非常无用的,可能会被删除:您想指定 strlen(s{1,2})
是有界的,但是 SIZE_MAX
中的 stdint.h
应该可以解决问题)。而且,\forall i, P(i) ==> Q(i)
的反面是 \exists i, P(i) && !Q(i)
(即不要在 ==>
之后使用 \exists
)。
最好用size_t
用于用作偏移量的 C 变量。否则对于非常大的字符串可能会发生奇怪的事情。
你缺少一些不变量。基本上,在 stringCompare
,您必须捕捉到以下事实:
i
停留在0
之间和 strlen(s1)
(分别为 strlen(s2)
)s1
的当前值实际上是\at(s1,Pre)+i
(同样适用于 s2
)s1
的所有元素和 s2
相等... unsigned char
在
return
声明会混淆WP。这无疑是 WP 本身的弱点。
stringLength
,还需要要求类似
valid_string(str)
的东西.但是,这一次你必须约束
strlen(str)
严格小于
SIZE_MAX
(假设您将返回类型和
result
的声明更改为
size_t
),因为
result
必须上
strlen(str)+1
没有溢出。
result
以
strlen(str)
为界,并且我们必须指出到目前为止所有字符都是非 0。
main
功能,WP 的另一个弱点阻止检查 stringCompare 的先决条件是否得到满足。如
hello
和
helli
被明确定义为字符数组,那么一切都会好起来的。
frama-c -wp -wp-rte file.c
证明(Frama-C 22.0 Titanium 和 Alt-Ergo 2.2.0)
#include <stdint.h>
#include <string.h>
#include <stdio.h>
/*@
requires validPointers: valid_read_string(s1) && valid_read_string(s2);
requires validLengthS1: n >= strlen(s1) >= 0;
requires validLengthS2: n >= strlen(s2) >= 0;
assigns \nothing ;
allocates \nothing ;
frees \nothing ;
behavior allEqual:
assumes \forall integer k; 0 <= k <= strlen(s1) ==> s1[k] == s2[k];
ensures \result == 0;
behavior SomeDifferent:
assumes \exists integer k; 0 <= k <= strlen(s1) && s1[k] != s2[k];
ensures \result != 0;
disjoint behaviors;
complete behaviors;
*/
int stringCompare(const char* s1, const char* s2, size_t n) {
if (s1 == s2)
return 0;
size_t i = 0;
/*@ assert \valid_read(s1) ; */
/*@ assert \valid_read(s2) ;*/
/*@ loop invariant index: 0 <= i <= strlen(\at(s1,Pre));
loop invariant index_1: 0<= i <= strlen(\at(s2,Pre));
loop invariant s1_pos: s1 == \at(s1,Pre)+i;
loop invariant s2_pos: s2 == \at(s2,Pre)+i;
loop invariant equal: \forall integer j; 0<= j < i ==> \at(s1,Pre)[j] == \at(s2,Pre)[j];
loop invariant not_eos: \forall integer j; 0<= j < i ==> \at(s1,Pre)[j] != 0;
loop assigns i , s1, s2; */
while (*s1 == *(s2++))
{
/*@ assert i <= n ; */
++i;
if (*(s1++) == '\0')
return 0;
}
return *(s1) - *(--s2);
}
/*@
requires valid_string(str);
requires strlen(str) < SIZE_MAX;
assigns \nothing ;
ensures rightResult: \result == strlen(\old(str));
ensures rightEndCharacter: str[\result] == '\0' ; */
size_t stringLength(const char* str) {
size_t result = 0;
/*@ loop assigns result ;
loop invariant 0 <= result <= strlen(str);
loop invariant \forall integer i; 0<= i < result ==> str[i]!=0;
*/
while (str[result++] != '\0');
return --result;
}
/*@ assigns \nothing ;
ensures \result == 0 ;*/
int main(void) {
const char hello[] = { 'h', 'e', 'l', 'l', 'o', '\0'};
const char helli[] = { 'h', 'e', 'l', 'l', 'i', '\0'};
/*@ assert \valid_read(&hello[0]) && \valid_read(&helli[0]) ; */
stringCompare(hello, helli, 5);
return 0;
}
关于c - 如何用 Frama-C 证明 C stringCompare 函数的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65213284/
如果我想要一个不区分大小写的字符串键控字典,在给定这些约束的情况下,我应该使用哪个版本的 StringComparer: 字典中的键来自 C# 代码或仅以英语语言环境(美国或英国)编写的配置文件 软件
为什么 String.IndexOf(String, StringComparison)需要 StringComparison并且不允许更一般的StringComparer ,甚至只是 ICompar
某些 .NET 方法使用 StringComparison作为参数,有些使用 StringComparer (通常采用 IComparer 的形式)。差异是显而易见的。是否有一些优雅的方法如何从 St
我有一个 UTF-8 字符串列表,我想使用 Enumerable.OrderBy 对其进行排序.字符串可能包含任意数量的字符集 - 例如,英语、德语和日语,或者它们的混合,甚至。 例如,这是一个示例输
我有一个带有街道名称的 SortedList Dim orderedListStreet As New Generic.SortedList(Of String, String)(StringComp
我正在寻找一个具有支持通配符 (*) 和大小写敏感的 StringComparer 的快速 .NET 类/库。有什么想法吗? 最佳答案 您可以将 Regex 与 RegexOptions.Ignore
我正在尝试序列化/反序列化字典,问题是我用 StringComparer.OrdinalIgnoreCase 创建字典比较器。 这是我遇到的问题的代码片段: var dict = new Dictio
我正在尝试为 .Net core 1.0 重新定位一个可移植的 C# 库。 一旦我获得了该语言的 CultureInfo 对象(通过调用者设置的委托(delegate)),我曾经做过类似的事情来获得该
我需要使用全局化规则来搜索文档中出现的所有字符串。伪代码是: var searchText = "Hello, World"; var compareInfo = new CultureInfo("e
.NET5 的新手,所以不确定这是否简单。我的解决方案中还有 5 个其他项目,它们都在 project.json 文件中有这个 "frameworks": { "net5": { } } 我需
我一直在使用 StringComparer.CurrentCultureIgnoreCase用于不区分大小写的比较和散列。但是在检查了引用源之后,我看到它在每次调用时都会创建一个新实例(那么它不应该是
StringComparer.InvariantCultureIgnoreCase Equals 对“”与“\0”返回 true,但 GetHashCode 对两个字符串返回不同的值。这是错误吗? v
这两个类有什么区别? 我使用了 System.StringComparer.OrdinalIgnoreCase() 和 System.StringComparison.OrdinalIgnoreCas
我想用 Frama-c 和 WP 插件来表示,下面编写的 stringCompare 函数充当“它应该”的作用 - 即:给定相同的输入字符串,该函数返回 0 并且结果不同于 0如果字符串不相同。我已经
我在我的数据库和我的 C# 代码之间实现了一个缓存层。这个想法是根据查询的参数缓存某些数据库查询的结果。数据库使用默认排序规则 - SQL_Latin1_General_CP1_CI_AS 或 Lat
我有一本字典Dictionary> .外部字典和内部字典都有一个相等比较器集(在我的例子中是 StringComparer.OrdinalIgnoreCase )。字典序列化和反序列化后,两个字典的比
免责声明:也许是微 YAGNI 优化,但听我说.. 问题是实现 不区分大小写 查找表。 我的老派方式:在填充字典时,在插入之前将键大写。当有人给你一个查找键时,将键大写。 新方法(我今天了解了):字典
我是一名优秀的程序员,十分优秀!