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

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");




int
main(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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值