Search code examples
cmallocrealloc

Undefined Behavior on inner realloc()


I'm attempting to write a PE parser, and my program contains two loops as shown below:

    size_t i = 0;
    while (condition_1) {
        struct _IMAGE_IMPORT_DESCRIPTOR64 *importDescriptorArray = malloc(sizeof(struct _IMAGE_IMPORT_DESCRIPTOR64));

        struct _IMAGE_THUNK_DATA64 *originalFirstThunkArray = malloc(sizeof(struct _IMAGE_THUNK_DATA64));

        size_t originalFirstThunkArrayIndex = 0;

        originalFirstThunkArray[originalFirstThunkArrayIndex].u1.ordinal = some_value; //set to a computed value

        while (condition_2) {
            originalFirstThunkArrayIndex++;

            originalFirstThunkArray = realloc(originalFirstThunkArray, originalFirstThunkArrayIndex * sizeof(struct _IMAGE_THUNK_DATA64));

            originalFirstThunkArrayOffset += sizeof(QWORD); //each element has its address stored as a QWORD, so I have to iterate QWORD-at-a-time.
            originalFirstThunkArray[originalFirstThunkArrayIndex].u1.ordinal = reverse_endianess_u_int64_t(readQWord(file, originalFirstThunkArrayOffset, QWORD_Buffer));
        }

        i++;
        importDescriptorArray = realloc(importDescriptorArray, i * sizeof(struct _IMAGE_IMPORT_DESCRIPTOR64));
    }

I can execute the outer loop n number of times and it will always give me the correct output. The inner loop however, randomly gives me correct answers or exits via a malloc: Incorrect checksum for freed object error message.

My codebase is beyond copy/pasting, but here are the definitions of the structures:

struct _IMAGE_IMPORT_DESCRIPTOR64 {
    union {
        DWORD Characteristics;
        IMAGE_THUNK_DATA32 OriginalFirstThunk;
    } u;
    DWORD timeDateStamp;
    DWORD forwarderChain;
    DWORD name;
    IMAGE_THUNK_DATA32 FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR64;

typedef struct _IMAGE_THUNK_DATA64 {
    union {
        QWORD forwarderString;
        QWORD function;
        QWORD ordinal;
        QWORD addressOfData;
    } u1;
} IMAGE_THUNK_DATA64;

I've narrowed down the line causing the error to the realloc() function of the inner loop, but I fail to understand why - is it because I'm accessing the array immediately after reallocation (but I am changing the index so that I edit data of the newly allocated space and not something else)?

What I am trying to do is allocate a single struct at a time (in order to conserve memory) because unless the structures are read until a certain condition is met, there is no other way to know how many of them exist.


Solution

  • originalFirstThunkArrayIndex is the index to the last element of the array, not the length of the array. You should reallocate with one extra element in the loop:

        originalFirstThunkArray = realloc(originalFirstThunkArray,
                                          (originalFirstThunkArrayIndex + 1) *
                                          sizeof(struct _IMAGE_THUNK_DATA64));
    

    Note that your identifiers are very long, making the code hard to read.

    There is a similar problem for i and importDescriptorArray...

    Finally a more important problem: importDescriptorArray is defined locally in the outer while loop body, so its value is lost at each iteration.