Thread: Memcpy Overflowing/Reading data that isn't mine

  1. #1
    Registered User
    Join Date
    Jul 2015
    Posts
    64

    Memcpy Overflowing/Reading data that isn't mine

    Hey guys,

    I'm sure this will be a quick one - it's probably just something that I've completely overlooked or have some fundamental misunderstanding of.

    Please consider (and tear apart) the following code:

    Code:
    wchar_t *str = L"Hello";    // Please note that this is passed as an LPWSTR in my project, but I thought I should "un-typedef" it to accommodate for non-Windows programmers :)
    wchar_t buf[3] = L"00";
    int element = 1;
    memcpy((void*) buf [element], (void*) str [1], sizeof(WCHAR));
    MessageBox(NULL, buf, str, MB_OK);
    This is a rough approximation of what I've been dealing with, minus a few frilly loops and element increments and whatnot. As you can probably tell, with the above demo code, I'm just trying to copy the character 'e' from L"Hello" into the first element (second character,) of 'buf'.

    I seem to be mistreating my arrays/pointers here, but I'm not entirely sure why this call is failing.

    Believe it or not, I've actually been staring at this code for a day or so now and I'm still no closer to diagnosing the problem.

    As such, any guidance would be hugely appreciated!

    Thanks very much,
    Abyssion
    Last edited by Abyssion; 11-10-2017 at 12:09 PM.

  2. #2
    Registered User
    Join Date
    Jun 2017
    Posts
    157
    Try this:
    Code:
      wchar_t *str = L"Hello
      wchar_t buf[3] = L"00";
      int element = 1;
      wcsncpy(&buf[1], &str[1], 1);
      MessageBoxW(NULL, buf, str, MB_OK);
    Why to "un-typedef" when you use MessageBox ?

  3. #3
    Banned
    Join Date
    Aug 2017
    Posts
    861
    not windows though, Linux

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main () {
       
        char *str = "Hello";    // Please note that this is passed as an LPWSTR in my project, but I thought I should "un-typedef" it to accommodate for non-Windows programmers :)
        char buf[3] = "00";
        
        memcpy(&buf[0], &str[1],1);
        printf("str %s : buf %s\n", str,buf);
        
         char *str1 = "HELLO";    // Please note that this is passed as an LPWSTR in my project, but I thought I should "un-typedef" it to accommodate for non-Windows programmers :)
        char buf1[3] = "00";
         
        
        buf1[0] = str1[1];
        printf("str1 %s : buf1 %s\n", str1,buf1); 
       
       return(0);
    }
    Code:
    userx@slackwhere:~/bin
    $ ./memcopy
    str Hello : buf e0
    str1 HELLO : buf1 E0
    Last edited by userxbw; 11-10-2017 at 12:44 PM.

  4. #4
    Registered User
    Join Date
    Jul 2015
    Posts
    64

    Smile

    Thank you both very much for your swift replies!

    Why to "un-typedef" when you use MessageBox ?
    Ahh yes, of course. That was an oversight on my part; I actually "un-typedef"ed as a last minute addition to my post and did not clock the MessageBox() call. My apologies!

    Thanks for the pointer though; both solutions seem to do the trick. Given that I am writing this for a library, I'd like to stay "as close to the hardware" as possible. In this situation, am I correct in thinking that userxbw's solution might be slightly more efficient with some implementations? (I'd assume that wcsncpy() might call memcpy() somewhere down the line and, as such, I'd imagine that the latter may be slightly more efficient. Please do correct me if I'm wrong.)

    Would anyone mind explaining, on a lower level, where I was going wrong in my initial code? I'm just trying to understand the semantics of it, that's all.

    In my initial call to memcpy, was I trying to dereference the 32/64 bits in memory (architecture dependent,) following the actual pointer to the first element of the array, as opposed to the first element itself?

    As always, I am learning a lot from my visits to these boards.
    Thanks very much!

  5. #5
    Banned
    Join Date
    Aug 2017
    Posts
    861
    casting as void * (pointers) not (de) referencing the address of same
    Code:
    
    
    Code:
    memcpy((void*) buf [element], (void*) str [1], sizeof(WCHAR));
    

    they are already pointers to, & gets the value inside of them. It is called reference or de reference. Someone an clue me in on that one too.




  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Would anyone mind explaining, on a lower level, where I was going wrong in my initial code? I'm just trying to understand the semantics of it, that's all.
    Looks like you forgot some syntax... then when that led to pointer vs. array problems you covered it up with casts, (and of course that still wouldn't work).

    buff[element] and str[1] - these are just 1 wchar_t. When you want to point somewhere into an array, you have a couple of options:

    a) arithmetic on base address: buff + element and str + 1 would work.
    b) subscript and take address: &buff[element] and &str[1]

    Of course, this all depends on types. If the element type of the array would have been a pointer itself (i.e. wchar_t *[3]) the answer wouldn't need the address of operator necessarily.

  7. #7
    Registered User
    Join Date
    Jul 2015
    Posts
    64
    Ahh yes, this makes a lot of sense.

    I think what threw me was that memcpy is expecting pointers (i.e. addresses,) whilst I was busy confusing myself with casts.
    Thanks very much for the explanations; it is clear to me now that I was trying to dereference the values stored at buf[element] and str[1], instead of passing the addresses of the values themselves.

    Lesson learned - I'm off to revisit the pointers tutorials on cprogramming.com
    Cheers folks and have a good weekend!

  8. #8
    Registered User
    Join Date
    Jun 2017
    Posts
    157
    In this situation, am I correct in thinking that userxbw's solution might be slightly more efficient with some implementations? (I'd assume that wcsncpy() might call memcpy() somewhere down the line and, as such, I'd imagine that the latter may be slightly more efficient.
    Why don't you write a little test to see what is faster?
    I guess there is no real difference with a modern optimizing compiler.
    If you really need to squeeze out a few nanoseconds consider using assember.

    BTW. Have you ever heard about premature optimization? http://wiki.c2.com/?PrematureOptimization

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to pass data types around -- I'm losing mine.
    By userxbw in forum C Programming
    Replies: 4
    Last Post: 09-22-2017, 07:10 AM
  2. memcpy access violation reading
    By Graefal in forum C Programming
    Replies: 4
    Last Post: 06-24-2016, 02:25 AM
  3. memcpy(msg->data+msg->dsize, ..)
    By securelinprog in forum C Programming
    Replies: 12
    Last Post: 03-06-2010, 11:23 PM
  4. append data at end of previous memcpy
    By metroflex in forum C Programming
    Replies: 5
    Last Post: 08-23-2009, 09:26 AM
  5. Overflowing string... any easy way to fix it?
    By Trauts in forum C++ Programming
    Replies: 2
    Last Post: 11-26-2002, 08:35 PM

Tags for this Thread