项目经验之谈 —— 利用编译器及C语言特性<位域>进行内存边界检测

来源:互联网 发布:nginx 伪静态 编辑:程序博客网 时间:2024/05/16 04:51

1.前言

在C语言中,边界检测总是一个让程序员头疼的问题,一不小心程序就崩溃了。C语言本身并没有提供边界检测的语法。但我们可以利用语言本身的一些特性及编译器进行边界检查。

2.校验内存边界

#define VERIFY_BOUNDARY(name,R) static char name ## dummy [sizeof(struct { unsigned char dummy:((R)?1:-1);})]  __attribute__ ((unused))

3.源码

#include <unistd.h>#include <stdio.h>#include <fcntl.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/types.h>#include <getopt.h>#include <stdlib.h>#include <string.h>#define ARRAY_CARDINALITY(Array) (sizeof(Array) / sizeof(*(Array)))#define VERIFY_BOUNDARY(name,R) static char name ## dummy [sizeof(struct { unsigned char dummy:((R)?1:-1);})]  __attribute__ ((unused))enum {    VIR_DAEMON_ERR_NONE = 0,    VIR_DAEMON_ERR_PIDFILE,    VIR_DAEMON_ERR_RUNDIR,    VIR_DAEMON_ERR_INIT,    VIR_DAEMON_ERR_SIGNAL,    VIR_DAEMON_ERR_PRIVS,    VIR_DAEMON_ERR_NETWORK,    VIR_DAEMON_ERR_CONFIG,    VIR_DAEMON_ERR_HOOKS,    VIR_DAEMON_ERR_AUDIT,    VIR_DAEMON_ERR_LAST};//========================================================================int virEnumFromString(const char *const*types,                      unsigned int ntypes,                      const char *type){    size_t i;    if (!type)        return -1;    for (i = 0; i < ntypes; i++)        if (0 == strcmp(types[i], type))            return i;    return -1;}const char *virEnumToString(const char *const*types,                            unsigned int ntypes,                            int type){    if (type < 0 || type >= ntypes)        return "unknow";    return types[type];}//========================================================================# define VIR_ENUM_IMPL(name, lastVal, ...)                               \    static const char *const name ## TypeList[] = { __VA_ARGS__ };      \    VERIFY_BOUNDARY(name,(ARRAY_CARDINALITY(name ## TypeList) == lastVal));\    const char *name ## TypeToString(int type) {                        \        return virEnumToString(name ## TypeList,                        \                               ARRAY_CARDINALITY(name ## TypeList),     \                               type);                                   \    }                                                                   \    int name ## TypeFromString(const char *type) {                      \        return virEnumFromString(name ## TypeList,                      \                                 ARRAY_CARDINALITY(name ## TypeList),   \                                 type);                                  \    }# define VIR_ENUM_DECL(name)                             \    const char *name ## TypeToString(int type);         \    int name ## TypeFromString(const char*type);//========================================================================VIR_ENUM_DECL(virDaemonErr);VIR_ENUM_IMPL(virDaemonErr, VIR_DAEMON_ERR_LAST,              "Initialization successful",              "Unable to obtain pidfile",              "Unable to create rundir",              "Unable to initialize libvirt",              "Unable to setup signal handlers",              "Unable to drop privileges",              "Unable to initialize network sockets",              "Unable to load configuration file",              "Unable to look for hook scripts",              "Unable to initialize audit system");intmain(int argc, char *argv[]){    printf("[ERR]: %s\n\r",virDaemonErrTypeToString(VIR_DAEMON_ERR_HOOKS));    return 0;}

4.执行结果

leon@netview:~/test/error$ ./error[ERR]: Unable to look for hook scripts

5.修改数组大小

上述执行结果是因为预期的数组大小跟实际的一致,可以通过修改数组大小,来检查效果。
修改数组大小后,编译结果:

leon@netview:~/test/error$ gcc -Wall -o error error.c error.c:15:74: error: negative width in bit-field ‘dummy’ #define VERIFY_BOUNDARY(name,R) static char name ## dummy [sizeof(struct { unsigned char dummy:((R)?1:-1);})]  __attribute__ ((unused))                                                                          ^error.c:61:5: note: in expansion of macro ‘VERIFY_BOUNDARY’     VERIFY_BOUNDARY(name,(ARRAY_CARDINALITY(name ## TypeList) == lastVal));\     ^error.c:83:1: note: in expansion of macro ‘VIR_ENUM_IMPL’ VIR_ENUM_IMPL(virDaemonErr, VIR_DAEMON_ERR_LAST, ^
0 0
原创粉丝点击