Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;memset/memcpy/strcpy实现-检查缓冲区溢出 我在C++中实现了基本的MySt/MeMCPY/STRCPY实现,这很好。但是,如果我要这样做,有没有办法检测缓冲区溢出:_C++ - Fatal编程技术网

C++;memset/memcpy/strcpy实现-检查缓冲区溢出 我在C++中实现了基本的MySt/MeMCPY/STRCPY实现,这很好。但是,如果我要这样做,有没有办法检测缓冲区溢出:

C++;memset/memcpy/strcpy实现-检查缓冲区溢出 我在C++中实现了基本的MySt/MeMCPY/STRCPY实现,这很好。但是,如果我要这样做,有没有办法检测缓冲区溢出:,c++,C++,例如: int main() { char *buf = (char *)calloc(10, sizeof(char)); __strcpy(buf, "Hello World"); // buffer size: 10, copy size: 12 (including '\0') - overflow } 实现(typedef unsigned int UINT): 在程序中无法检测到缓冲区溢出。操作系统正在检测它们。您只能检查代码中的潜在陷阱(if/else、

例如:

int main()
{
    char *buf = (char *)calloc(10, sizeof(char));
    __strcpy(buf, "Hello World"); 
    // buffer size: 10, copy size: 12 (including '\0') - overflow
}
实现(
typedef unsigned int UINT
):


在程序中无法检测到缓冲区溢出。操作系统正在检测它们。您只能检查代码中的潜在陷阱(if/else、断言、异常)。或者使用valgrind之类的分析工具

程序中无法检测到缓冲区溢出。操作系统正在检测它们。您只能检查代码中的潜在陷阱(if/else、断言、异常)。或者使用valgrind之类的分析工具

程序中无法检测到缓冲区溢出。操作系统正在检测它们。您只能检查代码中的潜在陷阱(if/else、断言、异常)。或者使用valgrind之类的分析工具

程序中无法检测到缓冲区溢出。操作系统正在检测它们。您只能检查代码中的潜在陷阱(if/else、断言、异常)。或者使用valgrind之类的分析工具

检测缓冲区溢出的更安全的方法是提供自己的
calloc
实现。在返回的块之前和之后提供一些字节填充,将它们设置为已知值(不是0或255),并且在调用
free
时检查它们是否未被触及。另外,在调用
free
后,您应该覆盖整个块(包括两侧的填充),以检查是否有双重
free
调用。

检测缓冲区溢出的更安全的方法是提供自己的
calloc
实现。在返回的块之前和之后提供一些字节填充,将它们设置为已知值(不是0或255),并且在调用
free
时检查它们是否未被触及。另外,在调用
free
后,您应该覆盖整个块(包括两侧的填充),以检查是否有双重
free
调用。

检测缓冲区溢出的更安全的方法是提供自己的
calloc
实现。在返回的块之前和之后提供一些字节填充,将它们设置为已知值(不是0或255),并且在调用
free
时检查它们是否未被触及。另外,在调用
free
后,您应该覆盖整个块(包括两侧的填充),以检查是否有双重
free
调用。

检测缓冲区溢出的更安全的方法是提供自己的
calloc
实现。在返回的块之前和之后提供一些字节填充,将它们设置为已知值(不是0或255),并且在调用
free
时检查它们是否未被触及。另外,在调用
free
后,您应该覆盖整个块(包括两侧的填充),以检查是否有双重
free
调用。

所有mem*函数都无效。它们复制(或设置)unsigned int类型的对象,而必须复制(或设置)unsigned char类型的对象。考虑到uu大小可以是奇数。 这些函数本身无法在不更改其声明的情况下检查缓冲区溢出

甚至第三个函数也是无效的

char *__strcpy(char *_Dst, const char *_Src)
{
    while ((*_Dst++ = *_Src++) != '\0');
    return _Dst;
}
函数内部的指针(u Dst)已更改并指向终止零。当您必须返回由Dst指向的字符串的第一个字符的地址时,从函数返回的此地址


这同样适用于前两个函数。

所有mem*函数都无效。它们复制(或设置)unsigned int类型的对象,而必须复制(或设置)unsigned char类型的对象。考虑到uu大小可以是奇数。 这些函数本身无法在不更改其声明的情况下检查缓冲区溢出

甚至第三个函数也是无效的

char *__strcpy(char *_Dst, const char *_Src)
{
    while ((*_Dst++ = *_Src++) != '\0');
    return _Dst;
}
函数内部的指针(u Dst)已更改并指向终止零。当您必须返回由Dst指向的字符串的第一个字符的地址时,从函数返回的此地址


这同样适用于前两个函数。

所有mem*函数都无效。它们复制(或设置)unsigned int类型的对象,而必须复制(或设置)unsigned char类型的对象。考虑到uu大小可以是奇数。 这些函数本身无法在不更改其声明的情况下检查缓冲区溢出

甚至第三个函数也是无效的

char *__strcpy(char *_Dst, const char *_Src)
{
    while ((*_Dst++ = *_Src++) != '\0');
    return _Dst;
}
函数内部的指针(u Dst)已更改并指向终止零。当您必须返回由Dst指向的字符串的第一个字符的地址时,从函数返回的此地址


这同样适用于前两个函数。

所有mem*函数都无效。它们复制(或设置)unsigned int类型的对象,而必须复制(或设置)unsigned char类型的对象。考虑到uu大小可以是奇数。 这些函数本身无法在不更改其声明的情况下检查缓冲区溢出

甚至第三个函数也是无效的

char *__strcpy(char *_Dst, const char *_Src)
{
    while ((*_Dst++ = *_Src++) != '\0');
    return _Dst;
}
函数内部的指针(u Dst)已更改并指向终止零。当您必须返回由Dst指向的字符串的第一个字符的地址时,从函数返回的此地址


这同样适用于前两个函数。

您可能需要所欠缓冲区的
大小,该大小可用于迭代多个位置以复制检查缓冲区溢出(如果有),如下所示

char *__strcpy(char *_Dst, const char *_Src, int size)
{
   while ((*_Dst++ = *_Src++) != '\0' && size--); //Iterate/copy to allocated Bytes
   return _Dst;
}


您可能需要所欠缓冲区的
大小
,可用于迭代多个位置以复制检查缓冲区溢出(如有),如下所示

char *__strcpy(char *_Dst, const char *_Src, int size)
{
   while ((*_Dst++ = *_Src++) != '\0' && size--); //Iterate/copy to allocated Bytes
   return _Dst;
}


您可能需要所欠缓冲区的
大小
,可以使用
#define GUARD_LEN = 4   // Arbitrary number of guard bytes.
#define GUARD_BYTE = 0xA5  // Arbitrary but recognizable: 10100101b
#define UNUSED_BYTE = 0x96 // Arbitrary but recognizable: 10010110b
#define FREED_BYTE = 0xC3  // Arbitrary but recognizable: 11000011b
#define MAX_ALLOCS = 1024  // Max # of malloc'ed buffers.
struct {
  void *addr;  // Address of malloc'ed buffer
  size_t len;  // Number of requested bytes
} Allocs[MAX_ALLOCS];

// Allocates and initializes memory.
void *chk_malloc(size_t length) {
  // Allocate memory for buffer + guard bytes.
  void *mem = malloc(length + 2*GUARD_LEN);
  if (mem == NULL) {
    return NULL;
  }

  // Initialize: [GUARD][UNUSED_BUFFER][GUARD]
  // Caller's usable memory starts after GUARD.
  void *buffer = mem + GUARD_LEN;
  memset(mem, GUARD_BYTE, GUARD_LEN);
  memset(buffer, UNUSED_BYTE, length);
  memset(buffer + length, GUARD_BYTE, GUARD_LEN);

  // Remember the address and length.
  // Simplified for demonstration; you may want this to be smarter.
  for (int i = 0; i < MAX_ALLOCS; ++i) {
    if (Allocs[i].addr == NULL) {
      Allocs[i].addr = buffer;
      Allocs[i].len = length;
      return buffer;
  }
  return NULL;  // Should also indicate MAX_ALLOCS is too small.
}

// Checks that buffer is filled with val.
bool chk_filled(void *buffer, char val, size_t len) {
  for (int i = 0; i < len; ++i) {
    if (buffer[i] != val) {
      return false;
    }
  }
  return true;
}

// Checks for over/underrun and releases memory.
void chk_free(void *buffer) {
  // Find the buffer in the array of alloc'ed buffers.
  for (int i = 0; i < MAX_ALLOCS; ++i) {
    if (Allocs[i].addr == buffer) {
      void *guard = buffer - GUARD_LEN;  // Initial guard bytes.
      if (!chk_filled(guard, GUARD_BYTE, GUARD_LEN)) {
        // Underrun
      }
      end_guard = buffer + Allocs[i].len;    // Terminal guard bytes.
      if (!chk_filled(end_guard, GUARD_BYTE, GUARD_LEN)) {
        // Overrun
      }

      // Mark the buffer as free and release it.
      memset(guard, FREED_BYTE, Allocs[i].len + 2*GUARD_LEN);
      Allocs[i].addr = -Allocs[i].addr;  // See text below.
      free(guard);
      return;
    }
  }
  // Error: attempt to free unalloc'ed memory.
}