0

I am trying to reallocate a char ptr which possess some data. After reallocating to a size that is larger than current, part of the data is being overwritten.

The relevant part of the code is as follows:

char *convertToBinary(char *src, int *fractionPosition, bool double_precision) {
    char *res = (char*)malloc(sizeof(char));
    int currentResultPos = 0, precision;
    int power = (strlen(src) - ((*fractionPosition) + 1)) * (-1);
    float decimalValue_i = convertToInt(src, 10, 0, (*fractionPosition) - 1, 0);
    float decimalValue_f = convertToInt(src, 10, (*fractionPosition) + 1,
                                        strlen(src) - 1, power);

    precision = determinePrecision(double_precision);
    res = fromDecimalToDstinationBase(res, &currentResultPos, 2, 
                                      decimalValue_i, &firstBinaryDigit);
    res = convertFractionIntoResult(res, currentResultPos, 2, 
                                    decimalValue_f, precision);
    *fractionPosition = currentResultPos - 1;

    return res;
}

char *fromDecimalToDstinationBase(char *res, int *resPos, unsigned int dstB,
                                  int decimalValue, char *firstDigit) {
    int valueLength, sum = 0, power = 0;

    while (decimalValue != 0) {
        sum += (decimalValue % dstB) * pow(10, power++);
        decimalValue /= dstB;
    }
    valueLength = countDecimalDigits(sum);
    res = copyIntToStr(res, sum, resPos, valueLength);
    return res;
}

char *copyIntToStr(char* res, int sum, int *resPos, int power) {
    int remainder;
    bool flag = true;
    res = (char*)calloc(power + (*resPos) + 1, sizeof(char));
    power--;
    while (sum != 0) {
        if (res[0] == '1' && flag) {
            addFractionPoint(res, resPos);
            flag = false;
        }
        remainder = sum % (int)pow(10, power);
        res[(*resPos)++] = (sum / pow(10, power--)) + '0';;
        sum = remainder;
    }
    res[*resPos] = '\0';
    return res;
}

char *convertFractionIntoResult(char *res, int logicalS, unsigned int dstB,
                                float decimalValue, unsigned int precision) {
     //here, logicalS = 5
     int physicalS = logicalS, resRemainderCounter = 0;
     float remainder = decimalValue;

     // here, res = "1.101"
     while (resRemainderCounter != precision) {
        if (physicalS == logicalS) {
            physicalS *= 2;
            res = (char*)realloc(res, physicalS * sizeof(char)); 
            // now, res = "1.1ÍÍÍÍÍÍÍýýýý"
        }

I looked all over for an explanation. Does anyone knows why this could happen? what I might've done wrong?

EDIT:

also, I tried to replace physicalS with some random really large number, and it didn't change anything.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Atalia.d
  • 131
  • 1
  • 13
  • 1
    For a start - you do not need the case for realloc - see http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc - Also how is `res` set – Ed Heal Nov 18 '16 at 23:15
  • use memset on res – maelswarm Nov 18 '16 at 23:16
  • 2
    Posting only a part of your program is not useful in diagnosing the problem. Please post a [mcve]. – R Sahu Nov 18 '16 at 23:18
  • maybe you are overwriting the space you originally allocated for `res` before you even get to `realloc`? How did you initially allocate `res` and what's the value of `physicalS`? – yano Nov 18 '16 at 23:19
  • hi, thanks for the comments. i'm pretty new at this. I added the relevant actions regarding the char pointer. – Atalia.d Nov 18 '16 at 23:36
  • the value of physicalS = logicalS is the current size of the pointer, before reallocating. in this case, if res = "1.101" then logicS supposed to be 5 – Atalia.d Nov 18 '16 at 23:39
  • if you're only allocating 5 bytes for the string "1.101" then that isn't enough,, you need at least 6 for the terminating NULL `'\0'` character. If you're writing 6 bytes into a 5-byte space then that's undefined behavior and nobody knows what will happen after that. – yano Nov 18 '16 at 23:47
  • yano, i just enlarged the size to 6. still the same – Atalia.d Nov 18 '16 at 23:55

2 Answers2

2

It appears you're using Microsoft's compiler and library. In debug mode, the library fills uninitialized portions of memory with various values that are intended to stand out when debugging in order to help you detect bugs.

The Í you see corresponds to 0xCD, which is the value the library uses to mark uninitialized portions of heap memory. The ý corresponds to 0xFD, which the library uses to mark areas beyond the ends of a heap allocation. Wikipedia can tell you a lot about these magic numbers.

So let's look at your code:

// here, res = "1.101"
// ...
physicalS *= 2;
res = (char*)realloc(res, physicalS * sizeof(char)); 
// now, res = "1.1ÍÍÍÍÍÍÍýýýý"

If it can, realloc should return a buffer of at least the requested size. It may be the original buffer, extended, or it may be a new buffer. If it's a new buffer, and the new buffer is larger than the original, then the contents of the original should be copied to the new one. The debug version of the library will fill the rest of the new buffer with 0xCD.

So this result tells me that when you thought res pointed to "1.101", it actually pointed to an unterminated buffer containing 1.1 that happened to be followed by 01 which may have been the result of a buffer overrun.

You then asked for a larger buffer, and the 1.1 was faithfully copied to the beginning, and the debug library then filled the remainder of the new buffer with 0xCD bytes to indicate that it is uninitialized heap memory.

In this case, I would use a debugger to watch the actual buffer sizes at each malloc and realloc and check if the code is actually overwriting the end of the buffer.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • [When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?](http://stackoverflow.com/q/370195/995714) – phuclv Nov 19 '16 at 09:56
-1

Found the error!

When addFractionPoint(res, resPos) was called, another reallocation has been made, which was smaller then the one that was made before that call.

Thanks everyone for your comments.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Atalia.d
  • 131
  • 1
  • 13