安全拷贝函数safe_memcpy实现分析

256 篇文章 3 订阅
149 篇文章 2 订阅

一 memcpy缺陷分析

1.memcpy原型:

#include <string.h>
void *memcpy(void *dest, const void *src, size_t n); #函数返回dest指针

2.缺陷分析:

(1)memcpy容易发生缓冲区溢出,如果dest长度小于待拷贝的字节数n,那么程序将发生缓冲区溢出;

(2)如果dest是高地址,src是低地址,拷贝可能发生错误,即源地址和目的地址重合部分在拷贝时被修改。

综上所述:memcpy参数较为简单,没有对程序安全性做进一步限制,将导致某些致命错误。

二 safe_memcpy

1.原型:

bool safe_memcpy(void *dst, const void *src, size_t len, const void *start, const void *end);
// dst指向目的地址
// src指向源地址
// len是待拷贝的字节数
// start指向目的地址开始地址
// end指向目的地址结束地址 即最后一个元素的后一个地址

2.实现分析:

safe_memcpy.hpp

#pragma once
#include <stdint.h>
#include <string.h>
static inline bool between(const uint8_t *start, const uint8_t *end, const uint8_t *p) {
    return (p < end) && (p >= start); // 注意是p < end不是p <= end
}
static inline bool safe_check(void *dst, size_t len, const void *start, const void *end) {
    if (len < 1) {
        return false;
    }
    if (!dst || !start || !end) {
        return false;
    }
    void *last_pos = ((uint8_t *)dst) + len - 1;
    if (last_pos < dst) {    // last_pos不能小于dst
        return false;
    }
    return between((uint8_t *)start, (uint8_t *)end, (uint8_t *)dst) &&     // dst在start与end之间
           between((uint8_t *)start, (uint8_t *)end, (uint8_t *)last_pos);  // last_pos即待拷贝区间最后元素地址也必须在start与end之间
}
static inline bool safe_memcpy(void *dst, const void *src, size_t len, const void *start, const void *end) {
    if (!safe_check(dst, len, start, end)) {
        return false;
    }
    if (!src) {
        return false;
    }
    memcpy(dst, src, len);
    return true;
}

(1)解决缓冲区溢出问题:调用safe_memcpy需要指定目的地址的开始和结束地址,safe_memcpy会检查l目标空间是否能够容纳待拷贝字节数;

(2)解决低地址向高地址拷贝错误:如果源地址和目的地址部分区间重叠,通过指定start和end,safe_memcpy使用between((uint8_t *)start, (uint8_t *)end, (uint8_t *)last_pos)可以进行安全性判断。

3.测试:

test.cpp

#include <iostream>
#include "safe_memcpy.hpp"
int main() {
    char src[64] = "123";
    char dst[64] = "";
    safe_memcpy(dst, src, strlen(src), dst, dst + 64);
    std::cout << dst << std::endl;
 
    return 0;
}

代码:https://github.com/wangzhicheng2013/safe_memcpy

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值