标签: splint

推荐的方法来跟踪C程序中数组越界访问/写入

考虑在C中编写一些不那么明显的算法的实现.例如,让我们在KN King的"C编程:现代方法,第2版"一书中找到它的递归快速排序,它可以从这里获得.最有趣的部分包括以下两个定义:

void quicksort(int a[], int low, int high)
{
    int middle;

    if (low >= high)
        return;

    middle = split(a, low, high);
    quicksort(a, low, middle - 1);
    quicksort(a, middle + 1, high);
}

int split(int a[], int low, int high)
{
    int part_element = a[low];

    for (;;) {
       while (low < high && part_element <= a[high])
           high--;
       if (low >= high)
           break;
       a[low++] = a[high];

       while (low < high && a[low] <= part_element)
           low++;
       if (low >= high) …
Run Code Online (Sandbox Code Playgroud)

c gdb splint memcheck cppcheck

20
推荐指数
1
解决办法
5561
查看次数

C移位表达式是否具有无符号类型?为什么夹板会警告右移?

对于以下程序:

int main(void)
{
    int value = 2;
    int result = value >> 1U;
    return result;
}
Run Code Online (Sandbox Code Playgroud)

... Splint 3.1.2给出警告:

splint_test.c: (in function main)
splint_test.c:4:18: Variable result initialized to type unsigned int, expects
                       int: value >> 1U
  To ignore signs in type comparisons use +ignoresigns
Run Code Online (Sandbox Code Playgroud)

Splint似乎声称有符号整数右移的表达式具有无符号整数的类型。但是,我可以在ANSI C90标准中找到的全部是:

结果E1 >> E2E1右移位E2位置。如果E1具有无符号类型或E1具有符号类型和非负值,则结果的值是商E1除以数量2的幂的整数部分E2

此代码的主要目标是带有大多数C90编译器的嵌入式系统。但是,我对编写符合标准的代码感兴趣。我一直在以C99模式在GCC和Clang上进行测试,因此可以restrict正常工作。

我的问题是:

  1. C标准是否对移位结果的类型提出任何要求?
  2. 做编译器吗?
  3. 如果不是,为什么夹板会发出此警告?

c code-analysis splint bit-shift language-lawyer

17
推荐指数
2
解决办法
731
查看次数

如何在我声明变量的地方忽略splint?

你知道我怎么能忽略我声明变量的地方?

我知道旧学校c告诉你在每个函数的开头都声明变量,但由于我是一个坏人,我喜欢声明接近我使用它们的地方.一个很好的例子就是把int i; 就在for(i = 0; ...)之前.

我们来看一个非常简单的例子

#include  <stdio.h>
int main()
{
    printf("Hello splint test\n");

    int i;
    for(i=5;i>0;i--)
    {
        printf("%2d...\n",i);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里夹板和大多数旧的c编译器想移动int i; 向上一行,或者放置{}循环声明和for循环.

现在问题是,如何关闭此检查?但保持其他检查是好的吗?

谢谢约翰


注1:我已经使用gcc警告(见下文)作为第一道防线,而valgrind作为第二道防线.但是我正在考虑将夹板添加到可以控制我的愚蠢的事情列表中;-)但是这个检查只是烦人的,

我使用的gcc警告:-Wall -W -Wextra -Wconversion -Wshadow -Wcast-qual -Wwrite-strings -Werror

注2:我知道这种不良行为可能带来的潜在可移植性问题.但我觉得它增加了可读性,也就是说不需要跳起来搜索这种类型的声明更有价值(我们可以在另一个线程中讨论).


更新:更多信息,我把上面的代码放在一个名为main.c的文件中.使用的平台是Ubuntu 8.04和gvim作为编辑器,这是我运行时splint的输出:

splint +gnuextensions main.c
Splint 3.1.1 --- 03 Nov 2006

Command Line: Setting +gnuextensions redundant with current value
main.c:8:8: Parse Error. (For help on parse errors, see splint -help
                 parseerrors.)
Run Code Online (Sandbox Code Playgroud)

这开辟了另外两个我以前没想过的问题.

  1. "冗余与当前价值",现在有什么价值?

  2. 为什么它是解析错误而不是警告?


更新::有补丁夹板支持这个问题的可能性,我还没有尝试过,但我认为这是解决方案.

c static-analysis lint splint c99

6
推荐指数
2
解决办法
3036
查看次数

splint调试解析错误

这是我第一次使用splint(来自Ubuntu存储库),我立即被WTF击中.错误消息:

nightcracker@nightcracker-pc:~/c/brainfuck$ splint brainfuck.c
Splint 3.1.2 --- 03 May 2009

brainfuck.c:17:6: Parse Error. (For help on parse errors, see splint -help
               parseerrors.)
*** Cannot continue.
Run Code Online (Sandbox Code Playgroud)

现在,显然它在第16行第6列看到了错误.让我们检查一下(发布完整代码):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum {
    CELL_CHUNK_SIZE = 1024,
};

typedef unsigned char cell;

int main(int argc, char *argv[]) {
    if (argc < 1) {
        fprintf(stderr, "ERROR: Not enough arguments\n");
        return 1;
    }

    FILE  *srcfile; // source file << THIS LINE APPARENTLY IS WRONG
    long srclen; // source file size
    char *bf; …
Run Code Online (Sandbox Code Playgroud)

c splint

6
推荐指数
1
解决办法
3697
查看次数

从夹板边界检查的奇怪行为

任何夹板专家在那里?我试图用夹板静态分析大量的项目,我有C.我看到过多数量的边界检查显然不能界失误的错误.我写了一个小测试程序试图找出问题,并在我对代码运行splint时注意到一些非常奇怪的警告.我有3个不同的例子.这是第一个:

int arr[3];

int main(void)
{
    int i;
    int var;

    arr[3] = 0; // (1) warning with +bounds, no warning with +likely-bounds

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

arr[3]+bounds我按照预期使用时,分配会生成警告,但在使用时不会执行任何操作+likely-bounds.什么是+likely-bounds连做?它似乎行不通.第二个例子:

int arr[3];

int main(void)
{
    int i;
    int var;

    for (i = 0; i < 3; i++)
        var = arr[i]; // (2) warning, even though I'm within the bounds.

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这个示例中,splint抱怨我正在读取数组的边界("内存读取引用内存超出分配的存储空间.")var = arr[i],即使我显然不是.这应该是一个警告,因为数组中的值没有初始化,但这不是我得到的警告.初始化数组中的最后一个值将清除错误(但不会初始化第一个或第二个).难道我做错了什么?在第三个例子中:

int arr[3];

int main(void)
{
    int i;
    int var;

    arr[3] …
Run Code Online (Sandbox Code Playgroud)

c arrays splint bounds

6
推荐指数
1
解决办法
337
查看次数

夹板:解析 for 循环中的错误

我使用夹板作为 c99 代码的静态分析器。

夹板似乎不太符合 c99。因此我应用了这个补丁:http : //www.cs.virginia.edu/pipermail/splint-discuss/attachments/20080718/52cc25f6/attachment.obj

现在,由于声明不在顶部,我没有得到解析错误

但是如果我在 for 语句中放入一个变量声明,我仍然会在 for 循环中遇到解析错误。例如:

for(int i = 0; i < 10; i++)
{
}
Run Code Online (Sandbox Code Playgroud)

一种解决方法是这样写:

int i;
    for(i = 0; i < 10; i++){
    }
Run Code Online (Sandbox Code Playgroud)

但是因为我不想适应我所有的 for 循环,我想知道是否有可用的补丁来解决这个问题。

c static-analysis splint

6
推荐指数
1
解决办法
1038
查看次数

.splintrc预处理器指令-D中的WhiteSpaces

我想splint在debian稳定的环境中运行我的一些源代码.
我需要给出预处理器指令-DUINT16_T='unsigned short',因为我经常需要它.我想将它放在我的.splintrc文件中.
从命令行运行时,splint -DUINT16_T='unsigned short' mysource.c它运行良好.如果将此行移动到我的.splintrc文件中

-DUINT16_T='unsigned short'
-I/usr/local/include/
Run Code Online (Sandbox Code Playgroud)

splint调用导致

Cannot list files in .splintrc files:
                                 short' (probable missing + or -)
  A flag is not recognized or used in an incorrect way (Use -badflag to inhibit
  warning)
Run Code Online (Sandbox Code Playgroud)

有人有解决方案吗?(请不要别名).

为了进行更深入的讨论,我将提供一个mnwe(最小的不工作示例)hello.c,这可能会有所帮助:

#include <stdio.h>

int main (void)
{
  UINT16_T returnvalue=0;
  printf ("Hello, world!\n");
  return returnvalue;
}
Run Code Online (Sandbox Code Playgroud)

命令gcc -DUINT16_T='unsigned short' hello.c运行良好 - splint -DUINT16_T='unsigned short' hello.c …

debian whitespace splint secure-coding preprocessor-directive

6
推荐指数
1
解决办法
215
查看次数

splint vs gcc:外部静态代码分析工具值得为C代码库做些什么?

我正在开发一个相当复杂的项目,作为一个额外的复杂功能,它是一个内核Linux模块.在这样的代码库上运行像splint这样的linting工具当然不是不可能的[1],但是琐碎的努力还不足以让事情顺利进行.

在我投入更多时间之前,我希望能在这个问题上获得一些反馈和意见.有足够的标志,gcc做了很多检查.在实践中使用单独的静态代码分析工具仍然值得吗?

[1] http://www.cs.virginia.edu/pipermail/splint-discuss/2005-January/000531.html

gcc splint linux-kernel

5
推荐指数
2
解决办法
1999
查看次数

夹板:要求不要检查系统标题

有没有办法停止splint分析包括 POSIX、libc 等在内的系统头文件?我运行-warnposix -preproc

% splint -warnposix -preproc my.c

/usr/include/unistd.h:220:8: Parse Error: Non-function declaration:
    __BEGIN_DECLS : int. (For help on parse errors, see splint -help
    parseerrors.)
*** Cannot continue.
Run Code Online (Sandbox Code Playgroud)

更新:

% splint +posixlib +unixlib -I/path/to/myheaders -I/usr/include/x86_64-linux-gnu my.c

/usr/include/asm-generic/int-ll64.h:19:24: Parse Error:
    Suspect missing struct or union keyword: __signed__ :
    int. (For help on parse errors, see splint -help parseerrors.)
Run Code Online (Sandbox Code Playgroud)

阅读夹板 FAQ14 后,我试图消除非标准关键字:

% splint +posixlib +unixlib -D__signed__= -I/path/to/myheaders -I/usr/include/x86_64-linux-gnu my.c

/usr/include/x86_64-linux-gnu/sys/syslog.h:200:66: Parse Error:
    Inconsistent function …
Run Code Online (Sandbox Code Playgroud)

c static-analysis splint

5
推荐指数
0
解决办法
1067
查看次数

Splint:定义前使用的局部变量

我知道局部变量在未设置时可以具有"随机"值,但是用指针设置局部变量的第一个值是不是很糟糕?例如:

void setValue(int* p_val)
{
    *p_val = …; /* Assignment does not use *p_val */
}

int main(void)
{
    int val;
    setValue(&val);
    printf("%d", val);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

其中setValue仅设置并且从不读取引用变量的值.Splint警告我val是"在定义之前使用",我对这个警告有点惊讶,因为我相信在执行printf之前设置val的值并使用val.夹板是否不够先进,无法识别用于设置初始值的参考?

c pointers splint definition

4
推荐指数
1
解决办法
126
查看次数