Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
589 views
in Technique[技术] by (71.8m points)

c - `realloc(): invalid next size` while trying to handle input of unknown size

I have the following code: function get_unlimited_input allocates a new string if NULL was passed, otherwise it just appends characters to the existing string. In the end it truncates excess bytes. (DEFAULT_BUFFER_SIZE was set to 5 to test case of many reallocations)

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

#define DEFAULT_BUFFER_SIZE 5

char *get_unlimited_input(char *buffer) {
    size_t current_size;
    if (buffer == NULL) {
        buffer = malloc(DEFAULT_BUFFER_SIZE * sizeof(char));
        current_size = DEFAULT_BUFFER_SIZE;
    } else {
        current_size = strlen(buffer) + DEFAULT_BUFFER_SIZE;
    }
    char *cursor = buffer + current_size - DEFAULT_BUFFER_SIZE;
    for (;;) {
        int current = getchar();
        *cursor = (char)current;
        cursor++;
        if (current == '
' || current == EOF)
            break;
        if (cursor >= buffer + current_size) {
            current_size += DEFAULT_BUFFER_SIZE;
            buffer = realloc(buffer, current_size);
            cursor = buffer + current_size - DEFAULT_BUFFER_SIZE;
        }
    }
    *cursor = '';
    buffer = realloc(buffer, cursor - buffer);
    return buffer;
}

int main() {
    printf(">");
    char *buffer = get_unlimited_input(NULL);
    printf(">");
    get_unlimited_input(buffer);
}

In most cases it works just fine, but if I pass 117 characters first, and then 12 it crashes:

>.....................................................................................................................
>............
realloc(): invalid next size
Aborted (core dumped)
python3 -c "print('.'*117+'
'+'.'*12)" | ./_buffer
realloc(): invalid next size
Aborted (core dumped)

What is the problem?

question from:https://stackoverflow.com/questions/65891246/realloc-invalid-next-size-while-trying-to-handle-input-of-unknown-size

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There are multiple problems in your code, causing the heap to become corrupted as the diagnostic indicates:

  • your assumption about the currently allocated size is incorrect: current_size = strlen(buffer) + DEFAULT_BUFFER_SIZE; is too optimistic. Since you reallocate the buffer to cursor - buffer bytes before returning it, there is no slack at the end of the string.

  • you test for ' ' and EOF after storing the byte to the array. This may be the intended behavior for the newline, but it is incorrect for EOF, which is not a character.

  • reallocating the buffer with buffer = realloc(buffer, cursor - buffer); is incorrect too: cursor points to the null terminator, hence you should use a size of cursor + 1 - buffer to keep the null terminator inside the allocated block.

Here is a modified version:

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

#define DEFAULT_BUFFER_SIZE  16  /* use address alignment as incremental size */

char *get_unlimited_input(char *buffer) {
    size_t current_size, pos;
    char *p;

    if (buffer == NULL) {
        pos = 0;
        current_size = DEFAULT_BUFFER_SIZE;
        buffer = malloc(DEFAULT_BUFFER_SIZE);
        if (buffer == NULL)
            return NULL;
    } else {
        pos = strlen(buffer);
        current_size = pos + 1;
    }
    for (;;) {
        int c = getchar();
        if (c == EOF || c == '')
            break;
        if (pos + 1 == current_size) {
            // reallocate the buffer
            current_size += DEFAULT_BUFFER_SIZE;
            p = realloc(buffer, current_size);
            if (p == NULL)
                break;
            buffer = p;
        }
        buffer[pos++] = (char)c;
        if (c == '
')
            break;
    }
    buffer[pos] = '';
    p = realloc(buffer, pos + 1);
    return (p != NULL) ? p : buffer;
}

int main() {
    printf("> ");
    char *buffer = get_unlimited_input(NULL);
    printf("got: %s
", buffer);
    printf("> ");
    get_unlimited_input(buffer);
    printf("got: %s
", buffer);
    return 0;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...