realloc is overwriting data [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
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.

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.

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.

Related

String or file entropy [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to write string\file entropy calculator. Here is code I wrote but it doesn't work:
double entropy(char* buf)
{
int* rgi = (int*)_alloca(256);
int* pi = rgi + 256;
double H = 0.0;
double cb = sizeof(buf);
for (int i = sizeof(buf); --i >= 0;)
{
rgi[buf[i]]++;
}
while (--pi >= rgi)
{
if (*pi > 0)
{
H += *pi * log2(*pi / cb);
}
}
return -H / cb;
}
What am I doing wrong?
I think you have 4 problems
1) The allocated memory is never initialized
2) Too little memory is allocated as you only allocate 1 byte for each integer
3) Use of char for buf may be a problem as char may be signed
4) sizeof(buf) gives you the size of a char pointer but not the size of the buffer
Besides that I think you make the code too complicated by iterating backwards.
Try this:
double entropy(unsigned char* buf, size_t bufsize)
{
int* rgi = (int*)_alloca(256 * sizeof *rgi);
memset(rgi, 0, 256 * sizeof *rgi);
double H = 0.0;
double cb = bufsize;
for (size_t i = 0; i < bufsize; ++i)
{
rgi[buf[i]]++;
}
for (int i = 0; i < 256; ++i)
{
if (rgi[i] > 0)
{
H += rgi[i] * log2(rgi[i] / cb);
}
}
return -H / cb;
}

figure out why my RC4 Implementation doesent produce the correct result

Ok I am new to C, I have programmed in C# for around 10 years now so still getting used to the whole language, Ive been doing great in learning but im still having a few hickups, currently im trying to write a implementation of RC4 used on the Xbox 360 to encrypt KeyVault/Account data.
However Ive run into a snag, the code works but it is outputting the incorrect data, I have provided the original c# code I am working with that I know works and I have provided the snippet of code from my C project, any help / pointers will be much appreciated :)
Original C# Code :
public struct RC4Session
{
public byte[] Key;
public int SBoxLen;
public byte[] SBox;
public int I;
public int J;
}
public static RC4Session RC4CreateSession(byte[] key)
{
RC4Session session = new RC4Session
{
Key = key,
I = 0,
J = 0,
SBoxLen = 0x100,
SBox = new byte[0x100]
};
for (int i = 0; i < session.SBoxLen; i++)
{
session.SBox[i] = (byte)i;
}
int index = 0;
for (int j = 0; j < session.SBoxLen; j++)
{
index = ((index + session.SBox[j]) + key[j % key.Length]) % session.SBoxLen;
byte num4 = session.SBox[index];
session.SBox[index] = session.SBox[j];
session.SBox[j] = num4;
}
return session;
}
public static void RC4Encrypt(ref RC4Session session, byte[] data, int index, int count)
{
int num = index;
do
{
session.I = (session.I + 1) % 0x100;
session.J = (session.J + session.SBox[session.I]) % 0x100;
byte num2 = session.SBox[session.I];
session.SBox[session.I] = session.SBox[session.J];
session.SBox[session.J] = num2;
byte num3 = data[num];
byte num4 = session.SBox[(session.SBox[session.I] + session.SBox[session.J]) % 0x100];
data[num] = (byte)(num3 ^ num4);
num++;
}
while (num != (index + count));
}
Now Here is my own c version :
typedef struct rc4_state {
int s_box_len;
uint8_t* sbox;
int i;
int j;
} rc4_state_t;
unsigned char* HMAC_SHA1(const char* cpukey, const unsigned char* hmac_key) {
unsigned char* digest = malloc(20);
digest = HMAC(EVP_sha1(), cpukey, 16, hmac_key, 16, NULL, NULL);
return digest;
}
void rc4_init(rc4_state_t* state, const uint8_t *key, int keylen)
{
state->i = 0;
state->j = 0;
state->s_box_len = 0x100;
state->sbox = malloc(0x100);
// Init sbox.
int i = 0, index = 0, j = 0;
uint8_t buf;
while(i < state->s_box_len) {
state->sbox[i] = (uint8_t)i;
i++;
}
while(j < state->s_box_len) {
index = ((index + state->sbox[j]) + key[j % keylen]) % state->s_box_len;
buf = state->sbox[index];
state->sbox[index] = (uint8_t)state->sbox[j];
state->sbox[j] = (uint8_t)buf;
j++;
}
}
void rc4_crypt(rc4_state_t* state, const uint8_t *inbuf, uint8_t **outbuf, int buflen)
{
int idx = 0;
uint8_t num, num2, num3;
*outbuf = malloc(buflen);
if (*outbuf) { // do not forget to test for failed allocation
while(idx != buflen) {
state->i = (int)(state->i + 1) % 0x100;
state->j = (int)(state->j + state->sbox[state->i]) % 0x100;
num = (uint8_t)state->sbox[state->i];
state->sbox[state->i] = (uint8_t)state->sbox[state->j];
state->sbox[state->j] = (uint8_t)num;
num2 = (uint8_t)inbuf[idx];
num3 = (uint8_t)state->sbox[(state->sbox[state->i] + (uint8_t)state->sbox[state->j]) % 0x100];
(*outbuf)[idx] = (uint8_t)(num2 ^ num3);
printf("%02X", (*outbuf)[idx]);
idx++;
}
}
printf("\n");
}
Usage (c#) :
byte[] cpukey = new byte[16]
{
...
};
byte[] hmac_key = new byte[16]
{
...
};
byte[] buf = new System.Security.Cryptography.HMACSHA1(cpukey).ComputeHash(hmac_key);
MessageBox.Show(BitConverter.ToString(buf).Replace("-", ""), "");
Usage(c):
const char cpu_key[16] = { 0xXX, 0xXX, 0xXX };
const unsigned char hmac_key[16] = { ... };
unsigned char* buf = HMAC_SHA1(cpu_key, hmac_key);
uint8_t buf2[20];
uint8_t buf3[8] = { 0x1E, 0xF7, 0x94, 0x48, 0x22, 0x26, 0x89, 0x8E }; // Encrypted Xbox 360 data
uint8_t* buf4;
// Allocated 8 bytes out.
buf4 = malloc(8);
int num = 0;
while(num < 20) {
buf2[num] = (uint8_t)buf[num]; // convert const char
num++;
}
rc4_state_t* rc4 = malloc(sizeof(rc4_state_t));
rc4_init(rc4, buf2, 20);
rc4_crypt(rc4, buf3, &buf4, 8);
Now I have the HMACsha1 figured out, im using openssl for that and I confirm I am getting the correct hmac/decryption key its just the rc4 isnt working, Im trying to decrypt part of the Kyevault that should == "Xbox 360"||"58626F7820333630"
The output is currently : "0000008108020000" I do not get any errors in the compilation, again any help would be great ^.^
Thanks to John's help I was able to fix it, it was a error in the c# version, thanks John !
As I remarked in comments, your main problem appeared to involve how the output buffer is managed. You have since revised the question to fix that, but I describe it anyway here, along with some other alternatives for fixing it. The remaining problem is discussed at the end.
Function rc4_crypt() allocates an output buffer for itself, but it has no mechanism to communicate a pointer to the allocated space back to its caller. Your revised usage furthermore exhibits some inconsistency with rc4_crypt() with respect to how the output buffer is expected to be managed.
There are three main ways to approach the problem.
Function rc4_crypt() presently returns nothing, so you could let it continue to allocate the buffer itself, and modify it to return a pointer to the allocated output buffer.
You could modify the type of the outbuf parameter to uint8_t ** to enable rc4_crypt() to set the caller's pointer value indirectly.
You could rely on the caller to manage the output buffer, and make rc4_crypt() just write the output via the pointer passed to it.
The only one of those that might be tricky for you is #2; it would look something like this:
void rc4_crypt(rc4_state_t* state, const uint8_t *inbuf, uint8_t **outbuf, int buflen) {
*outbuf = malloc(buflen);
if (*outbuf) { // do not forget to test for failed allocation
// ...
(*outbuf)[idx] = (uint8_t)(num2 ^ num3);
// ...
}
}
And you would use it like this:
rc4_crypt(rc4, buf3, &buf4, 8);
... without otherwise allocating any memory for buf4.
The caller in any case has the responsibility for freeing the output buffer when it is no longer needed. This is clearer when it performs the allocation itself; you should document that requirement if rc4_crypt() is going to be responsible for the allocation.
The remaining problem appears to be strictly an output problem. You are apparently relying on print statements in rc4_crypt() to report on the encrypted data. I have no problem whatever with debugging via print statements, but you do need to be careful to print the data you actually want to examine. In this case you do not. You update the joint buffer index idx at the end of the encryption loop before printing a byte from the output buffer. As a result, at each iteration you print not the encrypted byte value you've just computed, but rather an indeterminate value that happens to be in the next position of the output buffer.
Move the idx++ to the very end of the loop to fix this problem, or change it from a while loop to a for loop and increment idx in the third term of the loop control statement. In fact, I strongly recommend for loops over while loops where the former are a good fit to the structure of the code (as here); I daresay you would not have made this mistake if your loop had been structured that way.

strlen and free memory [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I allocated memory to a pointer to the maximum size of characters it could have.
Then I had to write code that will change its values depending on the value that was read from the file and I needed to know what is the length of the value in the pointer, so I used strlen() function.
I got what I needed.
The problem occured when I tried to free the memory of that pointer. The program crashed, I'm assuming im doing something "ilegal" and would like to know why and how to fix it.
here is part of the code:
char *StudID = (char*)malloc(sizeof(char)*15);
char *StudIDcpy = (char*)malloc(sizeof(char) * 15);
fread(stud[i].ID, sizeof(char), 4, in);
stud[i].ID[4] = '\0';
IDtemp = atoi(stud[i].ID);//convert ID string to integer and store value in IDtemp
StudIDcpy = itoba(IDtemp);//convert integer to binary number as a string
strcpy(StudID, StudIDcpy);
IDtemp = strlen(StudIDcpy);
free(StudIDcpy); // <---- I BELIEVE THIS IS WHERE IT CRASHES
Here is my itoba() function:
char *itoba(int a){
int i = 0, j;
char temp[15];
while(a){
if (a % 2)temp[i] = '1';
else temp[i] = '0';
i++;
a = a / 2;
}
temp[i] = '\0';
for (j = 0; j < i / 2; j++)swapc(&temp[j], &temp[i - j-1]);
return temp;
}
By the way I know I don't have to write sizeof(char) because it is equal to 1, but I write it anyways so I remember what value should be put there.
In your itoba() function, temp, a local array, which decays to a pointer to local variables, is returned.
After a function returns, its local variables are "free"ed immediately, allowing these memory space to be reused by someone else. Consequently, values held by them will soon be overridden by other values on the stack.
You can rewrite itoba() like this:
char *itoba(int a)
{
int i = 0, j;
char *temp = malloc(15); // <--- This line is different
while(a){
if (a % 2)
temp[i] = '1';
else
temp[i] = '0';
i++;
a = a / 2;
}
temp[i] = '\0';
for (j = 0; j < i / 2; j++)
swapc(&temp[j], &temp[i - j -1]);
return temp;
}
BTW: You should remove char *StudIDcpy = (char*)malloc(sizeof(char) * 15);, because the pointer value returned by malloc() is later discarded by itoba(IDtemp);. As a result, the memory allocated to StudIDcpy by this malloc() will never be freed, causing memory leak.

Add Two numbers present in two files and write it another file. numbers are too large not fit in integer bounds [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 days ago.
Improve this question
It's an interview question asked in amazon.
Given two very large numbers i.e., they dnt fit in integer bounds of 'C' lang, in two different files. tell me the sum of both the numbers.
Here's one way to do it, which could be modified to read strings of digits from two files, instead of from standard input via scanf. This will read strings of digits up to MAX_LEN in length.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LEN 10000
int main(int argc, char **argv)
{
/* read in first string */
char *fs = NULL;
fs = malloc(MAX_LEN);
if (!scanf("%s", fs)) {
fprintf(stderr, "Error: Could not read first string!\n");
return EXIT_FAILURE;
}
size_t fs_len = strlen(fs);
/* populate result array with first string digits */
short *res = NULL;
int res_len = MAX_LEN + 1;
res = malloc(sizeof(short) * res_len);
for (int res_idx = res_len - 1; res_idx >= 0; res_idx--) {
if (res_idx > (fs_len - 1)) {
res[res_idx] = 0;
continue;
}
int digit = fs[fs_len - res_idx - 1] - (int)'0';
res[res_idx] = digit;
/* error checking */
if ((res[res_idx] < 0) || (res[res_idx] > 9)) {
fprintf(stderr, "Error: Bad digit in fs at index %lu\n", fs_len - res_idx - 1);
return EXIT_FAILURE;
}
}
free(fs), fs = NULL;
/* read in first string */
char *ss = NULL;
ss = malloc(MAX_LEN);
if (!scanf("%s", ss)) {
fprintf(stderr, "Error: Could not read second string!\n");
return EXIT_FAILURE;
}
size_t ss_len = strlen(ss);
/* do the summation */
for (int ss_idx = ss_len - 1, res_idx = 0; ss_idx >= 0; ss_idx--, res_idx++) {
int digit = ss[ss_idx] - (int)'0';
/* error checking */
if ((digit < 0) || (digit > 9)) {
fprintf(stderr, "Error: Bad digit in ss at index %d\n", ss_idx);
return EXIT_FAILURE;
}
int temp_res = res[res_idx] + digit;
/* do we need to carry up? */
if (temp_res >= 10) {
res[res_idx + 1] += 1;
res[res_idx] = temp_res - 10;
}
else {
res[res_idx] = temp_res;
}
}
free(ss), ss = NULL;
/* print result */
for (int res_idx = (fs_len > ss_len ? fs_len : ss_len); res_idx >= 0; res_idx--) {
fprintf(stdout, "%d", res[res_idx]);
}
fprintf(stdout, "\n");
free(res), res = NULL;
return EXIT_SUCCESS;
}
It only keeps two arrays in memory at most, one char array and one short array. A char array would hold MAX_LEN bytes, and the short array would hold (MAX_LEN + 1) * 2 bytes, on systems where a short is two bytes.
If you read one character at a time from the two files, with the FILE pointer reading from the end of the file to the start, you could reduce this to just an array of short.
For further optimization, if you can bear the expense of two passes over the files (which might not be too expensive, given file caching), you could do a first pass on both strings to get their lengths. Given the larger of the two lengths, you can then allocate only as many short as you need to perform the summation, which would be the larger of the two lengths, plus one. Another option is to realloc your short array as you go along.

Where is the memory error in this code?

Someone asked me to write this code as an exercise in C. When they looked over what I had written, they immediately told me that there was a huge error regarding memory management. Being a simple exercise, they wanted me to find and fix this error. There must be a gap in my knowledge, or I must be overlooking something very obvious, because I cannot for the life of me find it. If someone could help me figure it out, I would be very grateful.
Here is the code:
char int_to_char(int number){
if (number > 9) return (char)(((int)'A') + number - 10);
else return (char)(((int)'0') + number);
}
int change_base(char* output, int buffer_size, int decimal_number, int base){
//check for valid parameters
if((base < 2) || (base > 26)) return -1; //range error
//ready variables
int output_i = 0;
int tmp_string_i = 0;
int dividend;
char remainder;
char * tmp_string = calloc(buffer_size, sizeof(char));
memset(output, '\0', buffer_size*sizeof(char));
//check for negative input
if(decimal_number < 0){
output[0] = '-';
dividend = -decimal_number;
output_i++;
}
else dividend = decimal_number;
//find digits
while(dividend / base != 0){
remainder = int_to_char(dividend % base);
dividend = dividend / base;
tmp_string[tmp_string_i] = remainder;
tmp_string_i++;
if(tmp_string_i + 1 > buffer_size){ //+1 for the extra negative sign
free(tmp_string);
return -2; //buffer size error
}
}
//add last digit to string
remainder = int_to_char(dividend);
tmp_string[tmp_string_i] = remainder;
//copy tmp_string to output in reverse order
for(; tmp_string_i >= 0; tmp_string_i--){
output[output_i] = tmp_string[tmp_string_i];
output_i++;
}
free(tmp_string);
return 0;
}
Also worthy of note, I have run this code through Valgrind to find any common memory mistakes, but it reports no errors. I don't know very much about the advanced features or nuances of Valgrind.
Lastly, I would be very happy for any comments on how I could improve the overall effectiveness and readability of this code.
If to say about one "huge error" then this error is the awful code itself.:)l
So if there are other errors then in fact they do not deserve to be discussed until the code will be rewritten.
For example do you know that if some integral number is negative then after statement like this
number = - number;
the number can be as before negative?:)
I think that "somebody" meant by "huge error" that your string is not zero-treminated.:) Consider a situation wnen the number has only one digit and buffer_size is equal to 1
And why does buffer_size have type int instead of size_t?
Also in my opinion it is a bad idea to allocate additional buffer for such a conversion.

Resources