A possible memory overwriting.

J

jammie_linux

Recently I came across a code which is quite similar to one shown
below:

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

typedef struct node
{
int data;
int arr[10];
struct node *next;
} node;



int main(void)
{
node block;
memset( &block, 0 , sizeof(block) );
printf("Main exiting...\n");
return 0;
}

In the above code, the memset function will make the "sizeof(block)
elements" in memory being pointed by &block equal to zero. But, isn't
the memset function overwriting the memory being pointed by &block
since the memory beyond the one being pointed by &block might be
belonging to something else?
Please help me to pin-point my mistake.
 
C

Christopher Benson-Manica

typedef struct node
{
int data;
int arr[10];
struct node *next;
} node;

node block;
memset( &block, 0 , sizeof(block) );

In the above code, the memset function will make the "sizeof(block)
elements" in memory being pointed by &block equal to zero.
Yes.

But, isn't
the memset function overwriting the memory being pointed by &block
Yes.

since the memory beyond the one being pointed by &block might be
belonging to something else?

The memory &block points to is block, which of course belongs to you.
The only problem with the memset() call is that it probably expects to
set next to NULL - it probably will work, but all-bits-0 is not
guaranteed to be a null pointer.
Please help me to pin-point my mistake.

You didn't make one in the code you posted.
 
S

SM Ryan

(e-mail address removed) wrote:

# In the above code, the memset function will make the "sizeof(block)
# elements" in memory being pointed by &block equal to zero. But, isn't

sizeof block bytes, not elements.
 
J

jammie_linux

SM said:
(e-mail address removed) wrote:

# In the above code, the memset function will make the "sizeof(block)
# elements" in memory being pointed by &block equal to zero. But, isn't

sizeof block bytes, not elements.

But the code for memset() indicates that it is sizeof(block)
"elements" and not "bytes" and in that case the program should crash
beacuse of the overwriting of the return address.


void *memset(void *s, register int c, register size_t n)
{
register char *s1 = *(char*)s;

while( n>0 )
{
*s1++ = c;
--n;
}

return s1;
}
 
R

Richard Bos

But the code for memset()

What code for memset()? There is no _the_ code for memset(). There is only
_the_ specification for memset(), and it states this:

# The memset function copies the value of c (converted to an unsigned char)
# into each of the first n characters of the object pointed to by s.
^^^^^^^^^^

Note: characters, so bytes. Not elements. It gets a void pointer, anyway, so
how is it to know in the first place how large an "element" is for the
original pointer?
void *memset(void *s, register int c, register size_t n)
{
register char *s1 = *(char*)s;

while( n>0 )
{
*s1++ = c;
--n;
}

return s1;
}

This is _a_ possible implementation for memset(), and it copies into the
first n characters (ergo bytes), not "elements", whatever they are.
Note, btw, that it converts c into a char, not explicitly into an unsigned
char. This is only valid for some (although many) implementations, not for
all.

Richard
 
P

pete

Richard said:
(e-mail address removed) wrote:
This is _a_ possible implementation for memset(),

No, it isn't.
1 The pointer s1 is assigned a char value
instead of a pointer value.
2 The type of s1 should be (unsigned char *).
 
R

Richard Bos

pete said:
No, it isn't.
1 The pointer s1 is assigned a char value
instead of a pointer value.
2 The type of s1 should be (unsigned char *).

*Sigh* Yes. As I noted in the next sentence. So this is _a_ possible way
to code memset() for many, but not all, C implementations. As I noted.

Richard
 
P

pete

*Sigh* Yes. As I noted in the next sentence.
So this is _a_ possible way
to code memset() for many, but not all, C implementations. As I noted.

No!!!
*(char*)s
should be
s

Those are two completely different initializations.
In order for the first one to work, the first byte
of the target object would have to contain a char value
that converts to a pointer to itself,
which besides being implementation defined,
is super extremely unlikely.
memset does not depend upon the value of the first byte
of the taget object, which is what (*(char*)s) is.
 
S

SM Ryan

(e-mail address removed) wrote:
#
# SM Ryan wrote:
# > (e-mail address removed) wrote:
# >
# > # In the above code, the memset function will make the "sizeof(block)
# > # elements" in memory being pointed by &block equal to zero. But, isn't
# >
# > sizeof block bytes, not elements.
#
# But the code for memset() indicates that it is sizeof(block)
# "elements" and not "bytes" and in that case the program should crash
# beacuse of the overwriting of the return address.

You're casting to a character pointer, so its elements are
bytes. But in something like

int x[2]; memset(x,0,sizeof x);

Assuming 4-byte ints, sizeof x is 8, and memset clears 8 bytes,
not 8 ints.

# void *memset(void *s, register int c, register size_t n)
# {
# register char *s1 = *(char*)s;
#
# while( n>0 )
# {
# *s1++ = c;
# --n;
# }
#
# return s1;
# }
#
#
#
 
P

pete

SM said:
(e-mail address removed) wrote:
#
# SM Ryan wrote:
# > (e-mail address removed) wrote:
# >
# > # In the above code, the memset function will make the
# > # "sizeof(block)
# > # elements" in memory being pointed
# > # by &block equal to zero. But, isn't
# >
# > sizeof block bytes, not elements.
#
# But the code for memset() indicates that it is sizeof(block)
# "elements" and not "bytes" and in that case the program should crash
# beacuse of the overwriting of the return address.

You're casting to a character pointer, so its elements are
bytes. But in something like

It's much more fucked up than that.
The value, >>>not the address<<<,
of the first byte of the target is being assigned to s1.
Even if it were to return s instead of s1, it still wouldn't work.
int x[2]; memset(x,0,sizeof x);

Assuming 4-byte ints, sizeof x is 8, and memset clears 8 bytes,
not 8 ints.

# void *memset(void *s, register int c, register size_t n)
# {
# register char *s1 = *(char*)s;
#
# while( n>0 )
# {
# *s1++ = c;
# --n;
# }
#
# return s1;
# }

void *mem_set(void *s, int c, size_t n)
{
unsigned char *p = s;

while (n-- != 0) {
*p++ = (unsigned char)c;
}
return s;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top