Home > Software engineering >  Runtime Error "heap-buffer-overflow" when returning string
Runtime Error "heap-buffer-overflow" when returning string

Time:02-06

I get a heap-buffer-overflow error when i compile th code:

char * reverseWords(char * s){
    int n = strlen(s);
    char *res = malloc(n   1);
    strcpy(res,s);
    char temp[100];
    int i = 0;
    int j = 0;
    for (i = 0; i < n; i  ){
        for (j = 0; j < n; j  , i  ){
            if (res[i] == ' ') break;
            temp[j] = res[i];
        }
        while (j > 0){
            j--;
            res[i - j - 1] = temp[j];
        }
    }
    return res;
}

I need reverse each words in string. I think the error is caused in this line (if (res[i] == ' ') break;) My idea is to find end of each words and reverse him. When I compile I get this error:

==30==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000005c at pc 0x5620553333a3 bp 0x7ffde02da850 sp 0x7ffde02da840
READ of size 1 at 0x60300000005c thread T0
    #2 0x7f359ea9c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x270b2)
0x60300000005c is located 0 bytes to the right of 28-byte region [0x603000000040,0x60300000005c)
allocated by thread T0 here:
    #0 0x7f359f6e1bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5 0x10dbc8)
    #3 0x7f359ea9c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6 0x270b2)
Shadow bytes around the buggy address:
  0x0c067fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c067fff8000: fa fa 00 00 00 04 fa fa 00 00 00[04]fa fa fa fa
  0x0c067fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8050: 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
==30==ABORTING

CodePudding user response:

The problem is in this line of code:

    for (j = 0; j < n; j  , i  ){

j starts at 0 in the inner loop, and happily counts to n for each successive "word".
When no SP is found to break the loop, this increment ventures off into the abyss.

Fix:

    for (j = 0; i   j < n; j  , i  ){

I find code like:

while (j > 0){
    j--;
    res[i - j - 1] = temp[j];

difficult to follow. Far too easy to be "off by one". Is j decreasing? Is the index increasing?

Here's an alternative version with comments.

char *reverseWords( char *s ) {
    // allocate a buffer to return as a string
    int n = strlen( s );
    char *res = malloc( n   1 );
    res[0] = '\0';

    int i = 0;
    while( i < n ) {
        // a buffer to hold one reversed "word"
        int j = 100;
        char word[100];
        word[ --j ] = '\0';

        // copy reversing characters of one "word"
        while( s[ i ] && s[ i ] != ' '  )
            word[ --j ] = s[ i   ];

        // append to the output
        strcat( res, word   j );

        // reproduce each intervening SP
        if( s[i] == ' ' )
            i  , strcat( res, " " );
    }

    return res;
}

CodePudding user response:

I have to admit, I had some fun debugging this code and refactoring bits of the program to derive a function that I believe meets the spirit of your project.

Regarding the error messages, I couldn't put my finger on the exact point, but I believe with the incrementing of both the "i" and "j" counters in your for loop, you probably were going out of bounds on the the string processing.

Regardless, following is a refactored version of your code with the main function performing a call to the function.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * reverseWords(char * s)
{
    int n = strlen(s);
    char * res = (char *)malloc(n * sizeof(char)   1);
    char temp[100];
    int i = 0;
    int j = 0;
    int k = 0;                              /* Work variable for adjusting counter variable "i" */

    for (j = 0; j < 100; j  )               /* Initialize the work arrays */
    {
        temp[j] = '\0';
    }

    for (j = 0; j <= n; j  )                /* Initialize the work arrays */
    {
        res[j] = '\0';
    }

    for (i = 0; i < n; i  )                 /* Just parsing through the character array passed in from the function */
    {
        for (j = 0; j < n; j  )
        {
            if (s[i   j] == ' ' || s[i   j] == '\0') break;     /* Added the test for the null terminator */
            temp[j] = s[i   j];
        }
        k = j;
        while (j > 0)
        {
            j--;
            res[i   k - j - 1] = temp[j];   /* Reversing the word that was found */
        }
        for (j = 0; j < 100; j  )
        {
            temp[j] = '\0';                 /* As a bit of caution, the work array is reinitialized */
        }

        i = i   k;                          /* Used to adjust the counter variable and also set the location */
        res[i] = s[i];                      /* This should store either a space or the null terminator       */
    }

    return res;
}

int main()
{
    char sentence[200];

    strcpy(sentence, reverseWords("Hello there my love - how are you?"));

    printf("%s\n", sentence);

    return 0;
}

Some points to note.

  • In the function, the character array referenced in the function call is used directly for the character and space testing, and then the reversed word(s) are copied into the work array.
  • Testing for the null terminator is also included when coming to the end of a word.
  • Using an abundance of caution, once the temporary character array had been parsed for copying the reversed word into the sentence array, it is reinitialized.

With that, following is the terminal output from the program test.

@Vera:~/C_Programs/Console/ReverseWord/bin/Release$ ./ReverseWord 
olleH ereht ym evol - woh era ?uoy

Give that a try to see if this meets the spirit of your project.

  • Related