I have a basic problem using memcpy and don't understand where the problem is. I show below the relevant parts of the code. The code seg. faults in the last right iteration of the loop. Why can't I index in to an memory area that is reserved?
Thank you in advance.
mystr->data = malloc(2048);
unsigned char buf[8500];
for (i=0;i<32;i++){
offset = i*256;
memcpy(&mystr->data[64*i],&buf[8+offset],64);
}
From the comments it'cs clear that my suspicion was right:
if sizeof( *mystr->data ) > 1 (because e.g. it's unsigned long long *data;) then you run beyond the end of the buffer because the offsets calculated by expressions like &mystr->data[64*i] are relative to the type, here it is mystr->data + 64*i*sizeof(*mystr->data) bytes which was up to 64*31*8 in your code.
You could either change the type, as you have done, or change the offsets (to &mystr->data[8*i] in your case) depending on what what seems 'right' semantically in your context
Related
Today I am trying to copy a unsigned long variable into the contents of an unsigned char * variable.
The reasoning for this is, I wrote an RC4 cipher which requires the key input to be a unsigned char *, I am using the SYSTEMTIME class to obtain a value & combining it with a randomly generated long value to obtain my key for RC4 - I am using it as a timestamp for a user created account to mark in my sqlite dbs.
Anyways, the problem I ran into is that I cannot copy the ULONG into PUCHAR.
I've tried
wsprintfA(reinterpret_cast<LPSTR>(ucVar), "%lu", ulVar);
and I've tried
wsprintfA((LPSTR)ucVar, "%lu", ulVar);
However, after executing my program the result in ucVar is just empty, or it doesn't even compute, and crashing the application.
[edit 1]
I thought maybe the memcpy approach would work, so I tried declaring another variable and moving it into ucVar, but it still crashed the application - i.e. It didn't reach the MessageBox():
unsigned char *ucVar;
char tmp[64]; // since ulVar will never be bigger than 63 character + 1 for '\0'
wsprintfA(tmp, "%lu", ulVar);
memcpy(ucVar, tmp, sizeof(tmp));
MessageBox(0, (LPSTR)ucVar, "ucVar", 0);
[/edit 1]
[edit 2]
HeapAlloc() on ucVar with of size 64 fixed my problem, thank you ehnz for your suggestion!
[/edit 2]
Can anyone give me some approach to this problem? It is greatly appreciated!
Regards,
Andrew
Unless you have ownership of memory you're trying to use, all kinds of things can happen. These may range from the error going unnoticed because nothing else already owns that memory, to an instant crash, to a value that disappears because something else overwrites the memory between the time that you set it and the time that you attempt to retrieve a value from it.
Fairly fundamental concepts when dealing with dynamic memory allocation, but quite the trap for the uninitiated.
I need to bin a hist variable like this, which is in a loop for p and bin,
hist[p][bin] = hist[p][bin] + 1;
When I comment this line, the code works( verified the p and bin variable print). However when I include this line the program terminates with segmentation fault. Further examining the bin variable gives me a huge negative integer ( -214733313 ), which leads to segmentation fault. The program runs normally when I comment this line and the bin variables are normal integer. Do I miss an obvious thing here?.
Thanks
If you're getting a -2147... you are basically reaching the max size of a signed integer, or 2^31 -1 (32 bits, 4 bytes, a C int).
If we assume this, then it's safe to say you're hitting memory where $FFFFFFFF is in it. I only ever see this in unallocated, generally random memory. It could be safe to assume then you are going out of bounds with your ask. You could have hist[p][bin] be the maximum memory of your array, and adding 1 is going out bounds.
I'm going through the K & R book and the answer to one of the exercises is troubling me.
In the solutions manual, exercise 1-22 declares a char array:
#define MAXCOL 10
char line[MAXCOL];
so my understanding is that in C arrays go from 0 ... n-1. If that's the case then the above declaration should allocate memory for a char array of length 10 starting with 0 and ending with 9. More to the point line[10] is out of bounds according to my understanding? A function in the sample program is eventually passed a integer value pos that is equal to 10 and the following comparison takes place:
int findblnk(int pos) {
while(pos > 0 && line[pos] != ' ')
--pos;
if (pos == 0) //no blanks in line ?
return MAXCOL;
else //at least one blank
return pos+1; //position after blank
}
If pos is 10 and line[] is only of length 10, then isn't line[pos] out of bounds for the array?
Is it okay to make comparisons this way in C, or could this potentially lead to a segmentation fault? I am sure the solutions manual is right this just really confused me. Also I can post the entire program if necessary. Thanks!
Thanks for the speedy and very helpful responses, I guess it is definitely a bug then. It is called through the following branch:
else if (++pos >= MAXCOL) {
pos = findblnk(pos);
printl(pos);
pos = newpos(pos);
}
MAXCOL is defined as 10 as stated above. So for this branch findblnk(pos) pos would be passed 10 as a minimum.
Do you think the solution manual for K & R is worth going through or is it known for having buggy code examples?
It is never, ever okay to over-run the bounds of an array in C. (Or any language really).
If 10 is really passed to that function, that is certainly a bug. While there are better ways of doing it, that function should at least verify that pos is within the bounds of line before attempting to use it as an index.
If pos is indeed 10 then it would be an out of bounds access and accessing an array out of bounds is undefined behavior and therefore anything can happen even a program that appears to work properly at the time, the results are unreliable. The draft C99 standard Annex J.2 undefined behavior contains the follows bullet:
An array subscript is out of range, even if an object is apparently accessible with the
given subscript (as in the lvalue expression a[1][7] given the declaration int
a[4][5]) (6.5.6).
I don't have a copy of K&R handy but the errata does not list anything for this problem. My best guess is the condition should < instead of >=.
Code above is fine as long as pos == 9 when its passed to that function . If pos ==10 when its passed then its undefined behaviour and .. you are correct , it should be avoided.
However it may or may not give segmentation fault .
my_type buffer[SOME_CONSTANT_NAME]; almost always is a bug.
Code like the one you present in the question is the source of the majority of security problems: when the buffer overflows, it invokes undefined behaviour, and that undefined behaviour (if it does not directly crash the program) can frequently be exploited by attackers to execute their own code within your process.
So, my advice is to stay away from all fixed buffer sizes and either use C++'s std::vector<> or dynamically allocate enough memory to fit. The Posix 2008 standard makes this quite easy even in C with the asprintf() function and friends.
// Works
int fnamesize=0;
fnamesize=message[0]<<24;
fnamesize+=message[1]<<16;
fnamesize+=message[2]<<8;
fnamesize+=message[3];
// Doesn't work
int fsize;
memcpy(&fsize,message,sizeof(int));
Can someone explain why the second one doesn't work? The memory I'm copying from, message is a char *. When I try to test the values of fnamesize and fsize, like printf("fsize is %d,fnamesize is %d",fsize,fnamesize);, the fsize gives an unexpected value, but fnamesize gives the value I expect.
Thoughts?
That's because of endianess, which means the layout of bytes in an int.
In windows, the second way will give you an int that has the opposite byte order, like this:
fsize=message[3]<<24;
fsize+=message[2]<<16;
fsize+=message[1]<<8;
fsize+=message[0];
Try changing the order of the array indices in your code that works, compare the result to the code that doesn't work, and look up the terms "big endian" and "little endian".
Greetings!
I have a simple program in qt on c.
There are two pointers to type short, used to read from file and store bits from values read.
sample code:
//(input is a FILE* which is opened and passed to the function)
//(output is also a FILE* which is also opened and passed to the function)
//1. Variables declaration
short* sample_buffer;
int buffer_size=1;
short samples_read;
unsigned long value_x=7;
short* nzb_buffer;
short buffer_position=-1;
int i;
//2.Memory allocation
sample_buffer= malloc(sizeof(short)*buffer_size);
nzb_buffer = malloc(sizeof(short)*value_x);
....
//3. Read from infile, one short at time, process and write it to outfile
do
{
//3.1. Read from input file
samples_read = fread(sample_buffer,sizeof(short),buffer_size, input);
//3.2. Switch position inside nzb_buffer one to the right,
// going back to zero if out of bounds
buffer_position=(buffer_position+1)%value_x;
....
//3.3. Put least significant bit of the just read short into nzb_buffer
nzb_buffer[buffer_position]=sample_buffer[0]%2;
....
//3.4. Write the short we just read from infile to the outfile
for (i=0;i<samples_read;i++)
{
fwrite(sample_buffer,sizeof(short),1, output);
}
} while(samples_read==buffer_size);
I've let unreliant pieces of code out. If you need to see something else please tell me.
Problem is, after like 10 or 15 operations of the loop, it crashes with "Segmentation fault" signal. It crashes on the fwrite() function.
I debugged and i use watch on sample_buffer. For some reason, on one exact step, the operation nzb_buffer[buffer_position]=sample_buffer[0]%2 makes sample_buffer become 0x0 (i belive, it becomes a null pointer).
This cannot be overflowing on nzb_buffer because buffer_position for that operation is 3 (out of 7 allocated for the particular array in malloc). And since each loop makes one write operation and shifts the carry, the operation of writing into nzb_buffer[3] has already happened before in the loop and did not nullify the pointer that time.
I am totally clueless what may be happening here.
Anybody has any ideas what is going on or how do i debug it?
Thanks in advance!
PS: Added comments "what the code does"
Your exit condition for the loop seems to be misplaced. I would do:
samples_read = fread(sample_buffer,sizeof(short),buffer_size, input);
while(samples_read==buffer_size){
[...]
samples_read = fread(sample_buffer,sizeof(short),buffer_size, input);
}