缓冲区溢出(Buffer Overflow)是一种常见的安全漏洞,发生在当程序尝试向一个固定长度的缓冲区写入过多数据时。这可能会导致超出缓冲区分配的内存范围,覆盖相邻内存区域的数据,从而可能引起程序崩溃或安全漏洞。
举个例子:
#include <cstring> #include <iostream> void vulnerableFunction(char* input) { char buffer[10]; // 缓冲区只有10个字节 strcpy(buffer, input); // 没有检查输入长度,直接复制 } int main() { char dangerousString[12]; // 创建一个长度为12的字符串 strcpy(dangerousString, "Hello, World!"); // 字符串长度为12,超出了缓冲区大小 vulnerableFunction(dangerousString); std::cout << "Program did not crash." << std::endl; return 0; }
在这个例子中,dangerousString
的长度为12个字节(包括最后的空字符 '\0'),而 buffer
只有10个字节。当 strcpy
被调用时,它将复制整个 dangerousString
到 buffer
,导致溢出。这将覆盖 buffer
后面的内存,可能破坏返回地址或其他重要的程序状态。
我们可以使用一个 MyString
类,用来封装 C 风格的字符串。
例如:
#include<iostream> #include<string> using namespace std; // 析构函数 // 在对象被销毁时调用 // MyString 封装了C风格字符串(MyString::buffer)使用字符时无需分配内存和释放内存 class MyString{ private: // 字符型的指针 char * buffer; public: // 构造函数 // 常量指针 MyString(const char *initString){ if(initString != NULL){ // 分配动态内存 使用new在堆上为buffer分配内存 大小为init string的长度+1 buffer = new char[strlen(initString)+1]; // 使用strcpy将initstring复制到新分配到内存中 strcpy(buffer,initString); } else{ buffer = NULL; } } ~MyString(){ if (buffer!=NULL){ delete []buffer; } } int GetLength(){ return strlen(buffer); } const char * GetString(){ return buffer; } }; int main(){ MyString sayhello("hihihiqhj"); cout << "buffer is :" << sayhello.GetLength() << endl; cout << "String is :" << sayhello.GetString() << endl; }
这个 MyString
类实现了基本的字符串封装功能,包括动态内存分配、复制、获取长度和获取字符串。析构函数确保了动态分配的内存在对象生命周期结束时被释放,避免了内存泄漏。然而,这个类还没有实现拷贝构造函数和赋值操作符,这意味着如果直接复制 MyString
对象,可能会发生浅拷贝,导致多个对象共享同一块内存,这可能会引起问题。