简体   繁体   English

为什么这段代码会触发MSVS2012的“写入溢出警告(C6386)”

[英]Why is this piece of code triggering “Write overrun warning (C6386)” with MSVS2012

I have the following piece of C code: 我有以下C代码:

#include <stdint.h>

typedef union{
    uint8_t c[4];
    uint16_t s[2];
    uint32_t l;
}U4;

uint32_t cborder32(uint32_t l)
{
    U4 mask,res;
    unsigned char* p = (unsigned char*)&l;
    mask.l = 0x00010203;
    res.c[(uint8_t)(mask.c[0])] = (uint8_t)p[0]; // <-- this line gives C6386
    res.c[(uint8_t)(mask.c[1])] = (uint8_t)p[1];
    res.c[(uint8_t)(mask.c[2])] = (uint8_t)p[2];
    res.c[(uint8_t)(mask.c[3])] = (uint8_t)p[3];
    return res.l;
}

And it triggers a Write overrun warning when running code analysis on it. 并且在对其运行代码分析时会触发Write overrun警告。 http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28C6386%29&rd=true http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k%28C6386%29&rd=true

The error is: 错误是:

C6386 Write overrun Buffer overrun while writing to 'res.c': the writable size is '4' bytes, but '66052' bytes might be written. C6386在写入'res.c'时写入溢出缓冲区溢出:可写大小为'4'字节,但可能写入'66052'字节。 Invalid write to 'res.c[66051]', (writable range is 0 to 3) 写入'res.c [66051]'无效,(可写范围为0到3)

And I just don't understand why ... Is there anyone who can explain me why? 我只是不明白为什么......有没有人可以解释我为什么?

I'd put this down as a potential bug in the Microsoft product. 我把它作为微软产品中的一个潜在错误。 It appears to be using the full value of mask.l ( 0x01020304 being decimal 66051 ) when figuring out the array index, despite the fact you clearly want mask.c[0] forced to a uint8_t value. 当计算出数组索引时,它似乎使用了mask.l的完整值( 0x01020304为十进制66051 ),尽管你明确希望mask.c[0]强制为uint8_t值。

So the first step is to notify Microsoft. 所以第一步是通知微软。 They may come back and tell you you're wrong, and hopefully give you the C++ standard section that states why what you're doing is wrong. 他们可能会回来告诉你你错了,并希望给你C ++标准部分,说明你为什么做错了。 Or they may just state the code analysis tool is "best effort only". 或者他们可能只是说代码分析工具是“尽力而为”。 Since it's not actually preventing you from compiling (and it's not generating errors or warnings during compilation), they could still claim VC++ is compliant. 由于它实际上并没有阻止你编译(并且它在编译期间没有产生错误或警告),他们仍然可以声称VC ++是合规的。

I would hope, of course, they wouldn't take that tack since they have a lot of interest in ensuring their tools are the best around. 我希望,当然,他们不会采取这种方式,因为他们非常有兴趣确保他们的工具是最好的。


The second step you should take is question why you want to do what you're doing in that way in the first place. 你应该采取第二个步骤就是为什么你想要做你在第一个地方,这样做的问题。 What you have seems to be a simple byte-ordering switcher based on a mask. 您所拥有的似乎是一个基于掩码的简单字节排序切换器。 The statement: 该声明:

res.c[(uint8_t)(mask.c[0])] = (uint8_t)p[0];

is problematic anyway since (uint8_t)(mask.c[0]) may well evaluate out to something greater than 3, and you're going to write beyond the end of your union in that case. 无论如何都是有问题的,因为(uint8_t)(mask.c[0])可能会评估大于3的东西,并且在那种情况下你将要写出超出你的联盟的末尾。

You may think that ensuring mask has no bytes greater than 3 may prevent this but it may be that the analyser doesn't know this. 您可能认为确保mask没有大于3字节可能会阻止这种情况,但可能是分析器不知道这一点。 In any case, there are many ways already to switch byte order, such as with the htons family of functions or, since your stuff is hard-coded anyway, just use one of: 在任何情况下,有许多方法可以切换字节顺序,例如使用htons系列函数,或者因为你的东西是硬编码的,所以只需使用以下方法之一:

res.c[0] = p[0]; res.c[1] = p[1]; res.c[2] = p[2]; res.c[3] = p[3];

or: 要么:

res.c[0] = p[3]; res.c[1] = p[2]; res.c[2] = p[1]; res.c[3] = p[0];

or something else, for stranger byte ordering requirements. 或者别的什么,对于更奇怪的字节排序要求。 Using this method doesn't cause any complaints from the analyser at all. 使用这种方法根本不会引起分析仪的任何抱怨。


If you really want to do it with the current mask method, you can remove the analyser warning (at least in VS2013 which is what I'm using) by temporarily supressing it (for one line): 如果你真的想用当前的mask方法来做,你可以通过暂时抑制它来消除分析器警告(至少在我正在使用的VS2013中)(对于一行):

#pragma warning(suppress : 6386)
res.c[mask.c[0]] = p[0];
res.c[mask.c[1]] = p[1];
res.c[mask.c[2]] = p[2];
res.c[mask.c[3]] = p[3];

(with casts removed since the types are already correct). (删除了强制转换,因为类型已经正确)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM