A possible memory overwriting.

Discussion in 'C Programming' started by jammie_linux, Nov 7, 2005.

  1. jammie_linux

    jammie_linux Guest

    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.
     
    jammie_linux, Nov 7, 2005
    #1
    1. Advertisements

  2. 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.
    You didn't make one in the code you posted.
     
    Christopher Benson-Manica, Nov 7, 2005
    #2
    1. Advertisements

  3. jammie_linux

    SM Ryan Guest

    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.
     
    SM Ryan, Nov 8, 2005
    #3
  4. jammie_linux

    jammie_linux Guest

    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;
    }
     
    jammie_linux, Nov 8, 2005
    #4
  5. jammie_linux

    Richard Bos Guest

    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?
    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
     
    Richard Bos, Nov 8, 2005
    #5
  6. jammie_linux

    pete Guest

    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 *).
     
    pete, Nov 8, 2005
    #6
  7. jammie_linux

    Richard Bos Guest

    *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
     
    Richard Bos, Nov 8, 2005
    #7
  8. jammie_linux

    pete Guest

    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.
     
    pete, Nov 8, 2005
    #8
  9. jammie_linux

    SM Ryan Guest

    wrote:
    #
    # SM Ryan wrote:
    # > 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;
    # }
    #
    #
    #
     
    SM Ryan, Nov 8, 2005
    #9
  10. jammie_linux

    pete Guest

    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.
    void *mem_set(void *s, int c, size_t n)
    {
    unsigned char *p = s;

    while (n-- != 0) {
    *p++ = (unsigned char)c;
    }
    return s;
    }
     
    pete, Nov 8, 2005
    #10
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.