0

I was writing some cstring-based code while I ran into this Visual Studio warning that I cannot seem to get rid of properly (i.e. without using a #pragma).

This answer basically solved this warning for me in the past. However, here the behaviour appears to be even more bizarre.

C6386: Buffer overrun while writing to 'str'.

The smallest piece of code required to replicate this error is as follows.

void test(const size_t len)
{
    char* const str = malloc(len + 1);
    if (str == NULL)
    {
        return;
    }
    for (size_t i = 0; i < len; i++) { }
    str[len] = '\0';
}

The last line triggers this warning message.

Warning message screenshot

Originally, I had code inside the loop which would write to the string, but apparently the code inside the loop has no effect on this warning. Filling the string with 'a' gives the same exact warning on the line after the loop.

If I remove the loop, even though it does nothing at all, the warning disappears.

Removing the NOOP loop removes the warning

If I add a 0 check for the len variable before the malloc call, then the warning also disappears. However, please note that this make no sense. The value I should be checking for is (size_t)-1, adding 1 to which would cause the argument passed to malloc to be 0, which could trigger this undefined behaviour that I had never heard of before crossing paths with this curious warning in VS.

Added len == 0 check

Is it me, or is it the Visual Studio warning system that is going crazy here? Because I feel like I am missing something completely obvious, yet I cannot see anything that could possibly go wrong with this code.

For reference, the len variable was originally the result of a wcslen call, which can never return (size_t)-1 simply because such string would be twice the length of the addressable memory.

I have been writing this kind of cstring manipulation code for nearly a decade now, and never once had I experienced any issues. This warning makes me wonder if I had been doing something wrong all this time.

Edit: The original code erroneously returned from a void function because it was a snippet from an originally much larger function. Here is a screenshot with a proper valueless return.

The value return from void function warning is irrelevant

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
natiiix
  • 1,005
  • 1
  • 13
  • 21
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/248681/discussion-on-question-by-natiiix-inconsistency-of-the-c6386-warning-in-visual-s). – Samuel Liew Oct 10 '22 at 01:49

1 Answers1

1

The warning message looks like this:

enter image description here

It shows: 'str' is a 0 byte array. The loop for (size_t i = 0; i < len; i++) may not hold.

I think the code should be changed to this:

void test(const size_t len)
{
    char* const str = malloc(len+1);
    if (str == NULL)
    {
        return;
    }
    for (size_t i = 0; i < len+1; i++) { }
    str[len] = '\0';
}

The warning wil disappeared. enter image description here

The parameter of malloc is set to len+1 just to prevent out-of-bounds errors.

If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item.

If the parameter is Len+1, malloc allocates an item of length at least 1 in the heap and returns a valid pointer to the item.

If you want to know the range of size_t len you can see this link.

In general, size_t should be used whenever you are measuring the size of something. It is really strange that size_t is only required to represent between 0 and SIZE_MAX bytes and SIZE_MAX is only required to be 65,535...

So len+1!=0

Jingmiao Xu-MSFT
  • 2,076
  • 1
  • 3
  • 10
  • Thanks for the input, but if I change the loop like that, I will have to put there extra logic to handle the last character differently from the rest of the string (by writing the termination character to it). The only way `str` could be a 0 byte array is if `len + 1` overflows to 0, but that practically cannot happen. Is this entire warning based around this possible overflow? Also, how can `len` be `NULL`? It's not even a pointer. So basically, it wants me to add a `len + 1 != 0` check? How did you get this warning in the Error List? I can only see it in the editor. – natiiix Oct 10 '22 at 09:02
  • There is a warning button in the upper part of the Error List window, which can show and hide warning information. It looks like a problem with the code but not the intellisense. – Jingmiao Xu-MSFT Oct 10 '22 at 09:36
  • I have all three levels enabled, and I don't see any of the IntelliSense warnings in the list anyway. Interesting... My Error List configuration looks exactly the same as in your screenshot. – natiiix Oct 10 '22 at 19:26
  • Did you choose Build+IntelliSense in the checkbox? – Jingmiao Xu-MSFT Oct 11 '22 at 01:38
  • Yep, as I said, it looks exactly the same. – natiiix Oct 11 '22 at 17:22
  • Maybe you can try to update or repair VS – Jingmiao Xu-MSFT Oct 12 '22 at 01:05
  • I have freshly installed it about 2 hours before creating this question, so I don't believe that's the issue, and I don't really feel like reinstalling a 50 GB piece of software over a minor issue like this. Regardless, I have worked my way around this warning, but I still consider the main text of the warning to be terribly misleading and providing no useful information toward fixing the issue in my context. It should just say that the expression can overflow to 0. – natiiix Oct 13 '22 at 02:29
  • If you have resolved this warning. You can consider adding an answer and changing its status to Answered. It will also help others to solve the similar issue. – Jingmiao Xu-MSFT Oct 13 '22 at 02:33
  • The question already includes a few ways to resolve the warning, but none of them are really proper. If you could just add a short note about checking if `len + 1 != 0` to your answer, I will gladly accept your answer. That is the solution that I used, and that is what I believe Microsoft was going for with their subtle warning message. – natiiix Oct 14 '22 at 03:35
  • I edit my answer about malloc and range of size_t, hope it can help you. – Jingmiao Xu-MSFT Oct 14 '22 at 06:26