recvfrom gives empty string

Discussion in 'C++' started by William, Mar 23, 2005.

  1. William

    William Guest

    I have declared the following struct:
    struct PropagateInfo {
    string type; // "registration", "gossip", "termination"
    int initiatePeerID;
    };

    which I used as follows:

    PropagateInfo* initiatePeerInfo = new PropagateInfo;
    initiatePeerInfo->type = type; // type is set to "registration"
    initiatePeerInfo->initiatePeerID = ID;

    cout << "type before sending to overseer: " << initiatePeerInfo->type << \
    endl; // prints "registration"

    // sending the struct initatePeerInfo to the server
    if ( (numBytes = sendto(sockfd, (void*)initiatePeerInfo, \
    MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&serv_addr, sizeof(struct \
    sockaddr))) == -1 ) {
    cerr << "send to: " << strerror(errno) << endl;
    exit(1);
    }
    cout << "bytes sent: " << numBytes << endl; // prints 512


    /**** server side *****/
    numBytes = recvfrom( sockfd, initiatePeer, MAX_UDP_PACKET_SIZE, 0, (struct
    sockaddr *) &peer_addr, &addrLen );
    // I have also tried sizeof(struct PropagateInfo) instead of
    MAX_UDP_PACKET_SIZE

    cout << "num bytes received: " << numBytes << endl; // prints 512
    initiatePeerID = ((PropagateInfo*)initiatePeer)->initiatePeerID;
    cout << "initiatePeerID: " << initiatePeerID << endl; // prints the
    correct ID

    type = ((PropagateInfo*)initiatePeer)->type;
    // error - nothing (i.e. "") is printed!!!
    cout << "type after receiving: " << type << endl;

    output:
    type after receiving:

    my question:
    Why is ((PropagateInfo*)initiatePeer)->type "registration" before sendto;
    but "" after recvfrom?!

    Thanks for your help.

    Documentation:
    http://linux.com.hk/PenguinWeb/manpage.jsp?name=send&section=2
     
    William, Mar 23, 2005
    #1
    1. Advertising

  2. "William" <> wrote...
    >I have declared the following struct:
    > struct PropagateInfo {
    > string type; // "registration", "gossip", "termination"


    Keep in mind that 'string' object does not _itself_ contain the chars
    it consists of. It allocates it elsewhere, usually in free store. So,
    writing out contents of 'type' as if they were consecutive bytes does
    not accomplish writing out "registration" even if type->c_str() actually
    yields "registration". That's the problem with serialisation in C++,
    it's just not that simple.

    > int initiatePeerID;
    > };
    >
    > [...]
     
    Victor Bazarov, Mar 23, 2005
    #2
    1. Advertising

  3. William schrieb:
    > I have declared the following struct:
    > struct PropagateInfo {
    > string type; // "registration", "gossip", "termination"
    > int initiatePeerID;
    > };


    [snip]

    > // sending the struct initatePeerInfo to the server
    > if ( (numBytes = sendto(sockfd, (void*)initiatePeerInfo, \
    > MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&serv_addr, sizeof(struct \
    > sockaddr))) == -1 ) {
    > cerr << "send to: " << strerror(errno) << endl;
    > exit(1);
    > }
    > cout << "bytes sent: " << numBytes << endl; // prints 512


    In addition to what Victor said, there is a *major* problem with your
    code, plus a few smaller ones:

    * the cast to void* is not necessary, but that you felt the need to use
    it should have rung every available alarm bell ;)
    * use C++ style casts instead
    * The big one: you're telling sendto() to send MAX_UDP_PACKET_SIZE
    bytes, which is almost guaranteed to be more than sizeof( PropagateInfo
    ), resulting in undefined behaviour and the potential for very nasty
    things to happen. Now sendto() only reads the data you pass, so it's
    fortunately only an invalid memory read. The output of 512 should warn
    you. PropagateInfo as declared above is never going to be 512 bytes
    large...

    > /**** server side *****/
    > numBytes = recvfrom( sockfd, initiatePeer, MAX_UDP_PACKET_SIZE, 0, (struct
    > sockaddr *) &peer_addr, &addrLen );


    * And now for the really big one:
    Here you're doing the same, but this time around with an operation
    (recvfrom()) that will _write_ past the end of initiatePeer. This kind
    of bug (buffer overflow) is the number one cause for security problems
    in software, especially when it comes to networking.

    > // I have also tried sizeof(struct PropagateInfo) instead of
    > MAX_UDP_PACKET_SIZE


    That would have been correct except for the more general problem as
    mentioned by Victor.

    > cout << "num bytes received: " << numBytes << endl; // prints 512


    You're quite lucky this statement was still executed instead of your
    program crashing. Actually, you're not so lucky because a crash would
    have had more warning potential than a somewhat working program :)

    With code as above in a program that receives data from the network,
    you're inviting everyone who can send packets to the machine it's
    running on to play with it. It shouldn't take more than a few minutes
    to create a UDP packet that will result in your program executing any
    code on your machine to the sender's delight. Remember, not only your
    client can send data to it - firewalls provide some protection, but
    maybe you intend your server to be connectable from the outside...

    Please get more familiar with how pointers work before you consider
    using them in networked applications. And memorise this: Never trust
    any data received from the network to be wellformed and benign - the
    same holds for any other kind of input. Expect the unexpected and write
    code that will cope nicely with the most bizarre input data imaginable.

    That said, I'm not at all trying to prevent you from exploring the world
    of socket programming nor pointers. Only the issue is very serious and
    you should be aware of the security implications.

    Cheers,
    Malte
     
    Malte Starostik, Mar 23, 2005
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?T3R0YXI=?=
    Replies:
    6
    Views:
    8,151
    =?Utf-8?B?TW9uZ283NDc=?=
    May 24, 2005
  2. Neil Young
    Replies:
    0
    Views:
    1,897
    Neil Young
    May 12, 2005
  3. Wim Deprez

    migrating recvmsg() to recvfrom()

    Wim Deprez, Jul 21, 2004, in forum: C++
    Replies:
    1
    Views:
    725
    Wim Deprez
    Jul 25, 2004
  4. Omega

    problem with recvfrom

    Omega, Nov 21, 2005, in forum: C Programming
    Replies:
    9
    Views:
    2,620
  5. Jack
    Replies:
    1
    Views:
    739
    Thomas J. Gritzan
    Feb 1, 2007
Loading...

Share This Page