强类型是否能防止缓冲区溢出?

4

在这种情况下,强类型(例如char)是否可以防止缓冲区溢出?

char a[100]
char b[100]

strcpy(a,unknownFunction); // unknownFunction could overflow b 
                           // since its length is unknown

strcpy(b,a); // can b still overflow a with its now, 
             // potentially overflowed size?

1
由于这是C++,请使用std::string和a = b;。 - Steve Townsend
5个回答

9

不。 strcpy() 函数会一直复制字符串直到找到一个空字符 ('\0')。如果 b[] 数组中没有空字符,它会继续在内存中查找,直到最终找到一个为空字符为止。


不是随机内存 - 在进程的地址空间中跟在b后面的任何内容。如果a或者b接近页面的末尾,它可能会在找到空字节之前发生错误。 - Steve Townsend
@Steve:确实。在进程的地址空间中,紧随b之后的内容很可能是堆栈帧中的返回地址。你好,漏洞利用! - Ken Simon
@Steve:我所说的“随机”是指具有随机内容的内存(就strcpy而言)…… - Oliver Charlesworth

5

C语言没有强类型系统。

C++的类型系统比较强,但并不是真正的强类型系统,因为它有reinterpret_cast。

要防止缓冲区溢出,类型信息必须(1)表示任意长度的字符串或(2)在类型本身中编码缓冲区长度。此外,类型判断系统应确保缓冲区长度小于或等于转换长度。

编辑:

通过一些小心处理,并忽略C++的强制转换能力,您可以在C++中编写一个“相当强”的无溢出缓冲区类。然而,根据该术语的一般定义,这并不是强类型化,因为仍然可能尝试在无效点访问缓冲区并且仍然可以编译。比我更擅长模板的人可能能够编写一个真正的模板类型安全缓冲区。

以下是我的建议:

template<int Length>
class SafeBuffer
{
    unsigned char[Length];
public:
    unsigned char& operator[](int index); //when implemented, throws exception on out-of-range access.
};

SafeBuffer<10> buf, foo;
SafeBuffer<9> bar;
buf = foo; //pass
buf = bar; //compile-time error.
buf[100]; //compiles, but generates error at runtime. 

请注意,我们利用模板的类型判断系统来强制编译错误 buf = bar。这是强类型系统的一个例子(还要注意,C++中的强制转换会破坏类型) 。

+1 是为了委婉地指出,对于所提出的问题而言,真正的答案是“撤回问题”。 - Derrick Turk
1
不,这并不是“不问问题”,只是有很多无知。我很多年都不理解类型系统——我需要上研究生课程一个学期才能掌握它。 - Paul Nathan

3
strcopy()函数的参数类型是char *。这意味着一旦你将数组传递给strcpy(),它就无法知道这些数组是固定大小的数组。对于该函数而言,它们只是指针,并且会继续复制元素,直到在b中找到\0为止。
主要问题是一旦函数接受了指针作为参数,它就无法确定它是指向单个对象的指针、指向动态分配缓冲区的指针还是在堆栈上分配的固定大小的数组。
所以答案是“不行”。

如果我传递的是char而不是char *会怎样? - Kevin Meredith
@Kevin:那样它就无法编译。你可以传递char *char[],然后转换为char * - Dima

1

即使使用 strcpy 函数,仍然可能会发生溢出,因为它只有在找到 NUL 字符时才会停止。

为了防止溢出,您应该使用 strlcpystrncpy 函数。

// using strlcpy
strlcpy(a, unknownFunction, 100);

// using strncpy
strncpy(a, unknownFunction, 100); 
a[99] = 0; // strncpy doesn't NUL-terminate the result

0
一般来说,strncpystrcpy 的更安全的替代品。

3
不,实际上并不是这样。只是存在一个容易被忽略的不同情况,导致了越界内存访问。 - Steve Jessop
@Steve: 我正在努力弄清楚这是什么。如果您的源字符串太长,那么您的目标字符串是否不会以空终止符结束? - Oliver Charlesworth
@Oli:没错,就是这个意思。这意味着在你本应该使用 strcpy 时可能会导致写入溢出,而改用 strncpy 后你将会在稍后的某个时候遇到读取溢出。这可能会减轻错误的严重性,但也可能不会。即使使用 strlcpy(或者自己编写一个函数来执行 strncpy 然后写入 NUL 字节),如果不检查截断,那么程序可能会进入程序员未曾预料的状态,从而导致错误、崩溃或易受攻击的安全漏洞。把这称为“更安全”的做法只会让人们忽略了正确处理字符串操作的重要性。 - Steve Jessop
其中“正确地”可以是:(1)尽可能地减少字符串处理,并获取正确的缓冲区大小,或者(2)使用一个字符串库(甚至是您自己编写的),该库分配所需的任何空间。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接