开发者

C++ memcpy() tricky use, behavior understanding needed

Decompilation so as to fix an old program can be painful.

As I'm a C# developer, there's something strange I don't understand. I would need a C++ tricks expert to help me understand the behaviour of "memcpy()".

Here's what I play with:

unsigned char sdata[] =  { 0x54, 
                           ... many values (=4100) ..., 
                           0x00 };

then

unsigned char BF_PTransformed[4*18] = { 0xC6, 
                                    ... many values (=72) ..., 
                                        0x7B };

and

struct BLOWFISH_CTX 
{
  unsigned long P[16 + 2];
  unsigned long S[4][256];
};

Here are the memcpy() calls:

void BFInit() 
{
    BLOWFISH_CTX* ctx = &this->BlowfishContext; 

    memcpy((void*)ctx->P, this->BF_PTransfo开发者_如何学JAVArmed, 18*4);
    memcpy((void*)ctx->S, (void*)this->sdata, 0x100*4*4);
}

Questions

I do not understand how this behaves with higher number of bytes than arrays destination length. Is that about data types?

Can someone explain it so it can be understood by a C# developer?

(And do not even try to mention the word Blowfish. 2 days on this "special" implementation made me sick ahah)


I do not undestand how does behave this with higher number of bytes than arrays destination length Is that about data types ?

First, memcpy operates on bytes, not array elements. So if you want to copy an array int[10], for example, you tell memcpy to copy 40 bytes (10*sizeof(int)). So the argument passed to memcpy (40 in this example) can be greater than the number of array elements (10), because each array element takes up more than one byte.

Second, if you genuinely tell memcpy to copy past the end of the array (say, if we passed 43 as the argument to memcpy in the above example), then you would have undefined behavior.

In C and C++, many error conditions are not required to be detected at compiletime or runtime. In C#, an exception would be thrown if you tried something illegal at runtime.

In C++, that happens in some cases too. But in many others, the error isn't detected at all, and what happens is undefined. The application may crash, or it may continue to running in a corrupted state. It may become a security vulnerability, or it may (in theory) make demons fly out of your nose. The language spec simply says nothing about what should happen.

And reading past the end of an array (as you'd do if you tell memcpy to copy more than the length of the array) is one such occasion. If you try to do it, your application has a bug, but there's no saying how it will behave when you try to run it. If you're lucky, it'll crash. In the worst case, it'll continue running, because then it'll be in an inconsistent state, and it might crash later (making the error much harder to diagnose), or it might, instead of crashing, simply produce the wrong results, or it may appear to work correctly when you run it on your computer, but exhibit any of these behaviors when your customer runs your application.

Undefined behavior is bad. Avoid at all costs.


The memcpy length parameter is in bytes not array elements.

The code would be better written as:

memcpy((void*)ctx->P, this->BF_PTransformed, 18 * sizeof(unsigned long));
memcpy((void*)ctx->S, (void*)this->sdata, 0x100 * 4 * sizeof(unsigned long));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜