2

I am working through some of the examples but am continually getting these Address Sanitizer heap-buffer-overflow errors. I can't for the life of me figure out where the potential overflow is here:

bool detectCapitalUse(char * word){
    
    int CapitalLet = 0;
    int WordLen = sizeof(word)/sizeof(char);
    bool result = 0;
    
    for (int i = 0; i < WordLen; i++)
    {
        if (word[i] >= 'A' && word[i] <= 'Z' )
        {
            CapitalLet++;
        }
    }
    
    if( CapitalLet == WordLen )
    {
        result = 1;
    }
    else if ((CapitalLet == 1) && (word[0] >= 'A' && word[0] <= 'Z'))
    {
        result = 1;
    }
    else if (CapitalLet == 0 )
    {
        result = 1;
    }
    else
    {
        result = 0;
    }    
    
    return result;
}

EDIT: Here's the complete error message.

=================================================================
==31==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000017 at pc 0x000000401850 bp 0x7ffcd5e90680 sp 0x7ffcd5e90670
READ of size 1 at 0x602000000017 thread T0
    #2 0x7f2bb38ea82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
0x602000000017 is located 0 bytes to the right of 7-byte region [0x602000000010,0x602000000017)
allocated by thread T0 here:
    #0 0x7f2bb4905f88 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10bf88)
    #4 0x7f2bb38ea82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
Shadow bytes around the buggy address:
  0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c047fff8000: fa fa[07]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==31==ABORTING
ryyker
  • 22,849
  • 3
  • 43
  • 87
nobby
  • 373
  • 1
  • 3
  • 15
  • 5
    The problem (at least in part) is here: `int WordLen = sizeof(word)/sizeof(char);`. The argument `word` (`char * word`) decays into a pointer upon being passed as an argument, so `sizeof(word)` is really going to return `sizeof` a pointer, not `sizeof` the array that you likely passed. And by the way, `sizeof(char)` is always `1` by definition. – ryyker Sep 15 '20 at 21:06
  • 1
    Use `strlen` to get the length. `sizeof` is the size of a pointer, probably 8, not the length of the allocated memory it points to. – Retired Ninja Sep 15 '20 at 21:08
  • The shown code is unlikely to result in a heap overflow. Please clarify what the observed misbehaviour is. The only problem I could see (apart from not doing what it is supposed to do) is with words shorter than a pointer. – Yunnosch Sep 15 '20 at 21:11
  • I am curious - would you please post the exact error for this exact code? It does not appear to have the syntax to cause a heap overflow. – ryyker Sep 15 '20 at 21:25

1 Answers1

2

Because nothing in your code uses heap memory, there is nothing that would possibly cause heap overflow, but the problem that can be addressed is here:

int WordLen = sizeof(word)/sizeof(char);. 

In the argument

(char * word)   

word decays into a pointer upon being passed as an argument, so

sizeof(word) 

is really going to return sizeof a pointer (4 bytes for 32bit addressing), not sizeof the array that you likely passed. And by the way, sizeof(char) is always 1 by definition.

Change the expression to:

int WordLen = strlen(word);

Changing this single line allowed your code to work as I believe it was intended. I tested it using the following calling method:

int main(void) 
{
    char word[] = {"this is A string"};
    bool res = detectCapitalUse(word);
    return 0;
}

One caveat:
If by chance you did use dynamically allocated memory in the calling function, or somewhere else that was not included in this post, and there was an attempt made to access that block of memory incorrectly, a heap-buffer-overflow could have been the result.

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • 1
    You are right. But do you think that this can cause what seems to be the misbehaviour observed by OP (i.e. a heap overflow)? I find the question either too unclear or to implausible to answer. Even if allowing for some creative interpretation of "heap overflow": – Yunnosch Sep 15 '20 at 21:14
  • @Yunnosch - I am editing, but yes I agree. At the very least there is some misunderstanding of the nature of the problem. – ryyker Sep 15 '20 at 21:17
  • @ryyker - You were correct, that was the issue. Though it's curious that this caused what LeetCode deemed a "Heap oveflow". I posted the complete text of the runtime error message (before the change to strlen) in my original. – nobby Sep 15 '20 at 21:24
  • @nobby - Yes, I saw the error message. Weird interpretation :) – ryyker Sep 15 '20 at 21:27