简体   繁体   中英

memcpy behaving in an unexpected way

Given below is my sample code :

int function1(unsigned char *out, int length){
unsigned long crypto_out_len = 16;
unsigned char crypto_out[16] = {0};
.......
//produces 16 bytes output & stores in crypto_out
crypto_function(crypto_out, crypto_out_len); 
//lets say crypto_output contents after are : "abcdefghijklmnop"
.......
memcpy(out, crypto_out,length);
return 0;
}

function2(){
unsigned char out[10] = {0};
function1(out, 10);
std::pair<unsigned char *,int> map_entry;
map_entry.first = out;
map_entry.second = 10;
}

Now, map_entry.first should contain : "abcdefghij", right?

But it contains "abcdefghij#$%f1^", some garbage associated with it. How should I avoid such unexpected behaviour so that map_entry.first should contain exactly "abcdefghij".

You are confusing char[] with strings. out does contain your expected data, but its not 0 terminated, so if you try to display it as a string it may look like it contains extra data. If the data is actually strings, you need to correctly 0 terminate them.

Since you haven't pasted the whole code, I can't be 100% sure but I think I know what's wrong. memcpy() is behaving correctly here, and everything is 100% defined behavior.

In this case, out is a 10-character string without a null terminator. You assign it to unsigned char* that contains no length information, and I suspect you simply don't use the number ten when you are referring to map_entry.first .

If you print it as unsigned char* or construct a std::string with it, C++ expects it to be a null-terminated string. Therefore, it reads it up until the first null character. Now, since out didn't have one it just runs over and starts reading characters on the stack after out which happen to be what you see as garbage.

What you need to do, is make sure that either the string is null-terminated or make sure that you always refer to it specifying the correct length. For the former, you'd want to make out 11-byte long, and leave the last byte as 0 :

function2(){
    unsigned char out[11] = {0};
    function1(out, 10);
    std::pair<unsigned char *,int> map_entry;
    map_entry.first = out;
    map_entry.second = 10;
}

Please also note that C++ will actually stop at the first null character it encounters. If your crypto_function() may output zero bytes in the middle of the string, you should be aware that the string will be truncated at the point.

For the latter, you'd have to use functions that actually allow you to specify the string length, and always pass the length of 10 to those. If you always work with it like this, you don't have to worry about zero bytes from crypto_function() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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