Thread: XOR on char buffer fails?

  1. #1
    Registered User
    Join Date
    Sep 2014
    Posts
    121

    XOR on char buffer fails?

    Hello. I`ve wrote a function for my utility to XOR char* buffer by a key, then to reverse it with the same key. Here is the code, it`s simple enough:

    Code:
    static inline char* XOR_buffer(const char* d, const char* k ) {
        char *newstr = (char*) malloc(sizeof(char)* strlen(d));
        newstr[0]='\0';
        printf("%d is size of string\n", strlen(d));
        char *begin = newstr;
        char* ret = begin;
        int len = strlen(k);
        int sizestr=0;
        while ( (*newstr++ = *d++) !='\0' ) sizestr++;
    #ifdef XORDBG
        printf("##[%s] is newstr\n", begin);
    #endif
        int i=0;
        char c;
        int j=0;
        while ( j < sizestr ) {
            begin[j] ^= k[j%len];
    #ifdef XORDBG
            printf("key[%c]", k[j%len]);
    #endif
            j++;
        }
        return ret;
    }
    When I rean it, consider from a functon pointer like that:

    Code:
    char* bufxor = "Now is the time for all good men to came and aid their party\nThe quick brown fox jumpped iver the lazy dog";
        printf("%s\n", bufxor);
        char* nstr = Utils.XOR_buffer(bufxor,"abc");
        printf("XOR:%s\n", nstr);
        nstr = Utils.XOR_buffer(nstr,"abc");
        printf("XOR:%s\n", nstr);
    The lengh of the string is reduced by the second XOR call. You can try it out, just define XORDBG to view the error message in the second pass to the buffer.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,403
    You assume that the d parameter of XOR_buffer will point to a null terminated string. This is not necessarily true when you're calling it on a buffer that stores the output of a previous call to XOR_buffer.

    I suggest that you declare XOR_buffer to modify the buffer in-place, i.e., instead of calling malloc, operate on the existing buffer, passing its length to XOR_buffer. For example:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    static inline char *XOR_buffer(char *buffer, size_t buffer_size, const char *key, size_t key_size) {
        /* ... this is just a simple for loop ... */
        return buffer;
    }
    
    int main(void) {
        char buffer[] = "Now is the time for all good men to came and aid their party\nThe quick brown fox jumpped iver the lazy dog";
        const size_t buffer_size = strlen(buffer); /* exclude null terminator from size */
        const char *key = "abc";
        const size_t key_size = strlen(key); /* exclude null terminator from size */
    
        printf("Before: '%s'\n", buffer);
    
        XOR_buffer(buffer, buffer_size, key, key_size);
        printf("XORed : '");
        for (size_t i = 0; i < buffer_size; ++i) {
            printf("%.2x", (int)buffer[i]);
        }
        printf("'\n");
    
        XOR_buffer(buffer, buffer_size, key, key_size);
        printf("After : '%s'\n", buffer);
    
        return 0;
    }
    Last edited by laserlight; 01-12-2015 at 02:52 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    It`s good idea, but I still need to pass just 2 strings to the parameters. I came up with new code. But, I am missing 2 char-s somewhere. It appeared that XOR - CAN XOR to '\0' and return unexpected null terminated buffer. Here is the fix and check:
    Code:
    static inline char* XOR_buffer(const char* d,const char* k) {
        const int stringl = strlen(d);
        const int klen = strlen(k);
        char* privateXorBuff = (char*) malloc(sizeof(char)* stringl);
        char* begin = privateXorBuff;
        char* ret = begin;
        int j=0;
        int h=0;
        for(j=0,h=j+1; h < stringl; j++,h++) {
            char* c = Utils.getStringFromTo(d,j,h);
            c[0] ^= k[j%klen];
            if ( c[0] == '\0') {
                c[0] ^= k[j%klen];
            }
            privateXorBuff[j] = c[0];
        }
        return ret;
    }
    Actually if XOR makes a null terminator - dexor it. But, in my code:
    Code:
    char *buf = "Now is the time for all good men to came and aid their party\nThe quick brown fox jumpped iver the lazy dog";
        char* bufxor = Utils.XOR_buffer(buf, "abc123");
        char* dexor = Utils.XOR_buffer(bufxor, "abc123");
        printf("\n\nXOR:%s\n\n", bufxor);
        printf("\n\nDEXOR:%s\n\n", dexor);
    The last printf prints "Now is the time for all good men to came and aid their party\nThe quick brown fox jumpped iver the lazy d", the DOG last 2 chars are missing. There must be some thing I am missing.

  4. #4
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Oh I`ve fixed the missing char. Appearst that the for loop MUST check for equallity too:
    Code:
     for(j=0,h=j+1; h <= stringl; j++,h++) { /*IMPORTANT*/
            char* c = Utils.getStringFromTo(d,j,h);
            c[0] ^= k[j%klen];
            if ( c[0] == '\0') {
                c[0] ^= k[j%klen];
            }
            privateXorBuff[j] = c[0];
        }
    Why, tho, I can`t tell but is working.

  5. #5
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Here is some example output:
    Code:
    BEFORE XOR:Now is the time for all good men to came and aid their party
    The quick brown fox jumpped iver the lazy dog            sasdasdsadsds 
    asdasd  OOOOOOOOOOOOOOOOOOOOpppp ooooooooooooooooo hereeee wwwww goooo long one looong and
    
    
    
         many many testing garbage strings11111111111111111112222222222222     
    
    
    
    
    XOR:/ [@ATGT\B]^ U^CE]TRCP[WAT[AACFJk6TBcZQ _UC[G^UZF[BPHJAVABCABCARBV@aUAkUS@BC~}|.-,~}|.-,~}|.-,~}C]\ ^]\ ^]\ ZVTWFE ^]   V\C]]\S]hi;8:A_K HGX\TACPRCBFABPSR1PSR1PSR1SPQ2SPQ2Akk;
    
    
    
    DEXOR:Now is the time for all good men to came and aid their party
    The quick brown fox jumpped iver the lazy dog            sasdasdsadsds 
    asdasd  OOOOOOOOOOOOOOOOOOOOpppp ooooooooooooooooo hereeee wwwww goooo long one looong and
    
    
    
         many many testing garbage strings11111111111111111112222222222222     

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,403
    Quote Originally Posted by heatblazer
    It appeared that XOR - CAN XOR to '\0' and return unexpected null terminated buffer.
    That is what I told you earlier: "You assume that the d parameter of XOR_buffer will point to a null terminated string. This is not necessarily true when you're calling it on a buffer that stores the output of a previous call to XOR_buffer."

    I actually wrote the program that I posted in post #2 such that it compiles and runs as expected. I replaced a for loop having a single line as the loop body with the comment. That line appears in some form in your code in post #1. Really, it is that simple. If you really want to use malloc with my suggested approach, you can still do so, e.g., in the main function (and remember to call free).

    If you want to continue over-complicating with malloc in XOR_buffer, trying to handle a null terminated string input instead of a buffer determined by a size parameter, go ahead and good luck debugging.

    EDIT:
    Quote Originally Posted by heatblazer
    Why, tho, I can`t tell but is working.
    Oh, you did manage to get it to work, but you don't know why? That's a Bad Thing.
    • You have a memory leak from post #1 that you probably have not fixed (you assigned to nstr when it points to memory returned by malloc, before calling free).
    • In this version that you say works, you call Utils.getStringFromTo, but why on earth that is necessary, I have no clue.
    • If you really want to treat privateXorBuff as a null terminated string, then you forgot to allocate space for the null character.
    • Why do you have privateXorBuff, begin, and ret? Your only use for begin is to use it to initialise ret, and your only use of ret is to return it, which would not be wrong if you modify the privateXorBuff pointer itself, but you don't.
    • Why do you need both j and h?

    In summary, your loop is inexplicably complicated: you're just iterating over two arrays of char simultaneously. If you know the sizes of the arrays (or the part thereof that you want to iterate over), doing the iteration is trivial. The portion of the buffer that you want to iterate over is determined by the null character since it is initially a null terminated string, but once you've past that, you just need to retain this size and you're good to go.
    Last edited by laserlight; 01-12-2015 at 05:11 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    I`ve read you carefully. OK, so the code you proposed in your first post, actually must be called for char array. Is that so? I can`t just call
    Code:
     XOR_buffer("bla bla bla", strlen("bla bla bla"), "abc", strlen("abc"));
    since they are unmutable. I still have to copy the returning buffer. I can`t really see how to avoid malloc. Imagine I can`t use the char array you proposed as the mutable string.

  8. #8
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Assume that I will recieve char pointers, not char arrays. Here I`ve reworked it a bit:
    Code:
    #ifdef XORVER1
    static inline char* XOR_buffer(const char* d,const char* k) {
        const int stringl = strlen(d);
        const int klen = strlen(k);
        char* privateXorBuff = (char*) malloc(sizeof(char)* stringl);
        myHeap[hIterator++] = privateXorBuff; //add to heap
        int i; char c;
        for (i=0; i < stringl; i++) {
            c = d[i] ^ k[i%klen];
            if ( c == '\0') c ^= k[i%klen];
            privateXorBuff[i] = c;
        }
        return privateXorBuff;
    }
    #else
    But really, I`d like to stick with the idea, that the parameter char buff will be copied then returned. I`ve freed the 2 leaks I`ve made. Valgrind reported 0 leaks.
    [EDIT] I`ve added test heap to prevent leaks in the utils.c source:
    Code:
    ...
    #define HSIZE 512000
    static char* myHeap[HSIZE];
    static int hIterator = 0;
    Each call to malloc assigns the a copy ptr to the heap, and I have a function that iterrates in the end to free all. As you`ve said in one of my posts "poor man algorithm" but prevents the leaks now.
    Last edited by heatblazer; 01-12-2015 at 07:08 AM.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,403
    Quote Originally Posted by heatblazer
    OK, so the code you proposed in your first post, actually must be called for char array. Is that so?
    Yes, or to a dynamic array of char.

    Quote Originally Posted by heatblazer
    I still have to copy the returning buffer. I can`t really see how to avoid malloc. Imagine I can`t use the char array you proposed as the mutable string.
    Then call malloc:
    Code:
    char *buffer = malloc(sizeof("bla bla bla"));
    if (buffer)
    {
        strcpy(buffer, "bla bla bla");
        const size_t buffer_size = strlen(buffer);
        XOR_buffer(buffer, buffer_size, "abc", strlen("abc"));
        // ...
        free(buffer);
    }
    You might ask why I bother with having a separate size parameter for the key when it does not change: well, consider that this then allows you to specify a key with embedded null characters, similiar to how the buffer might contain embedded null characters.

    Quote Originally Posted by heatblazer
    I`d like to stick with the idea, that the parameter char buff will be copied then returned.
    Check out the functions from <string.h>. They don't do that. This way, you can choose to use them with malloc, or not. Perhaps you would use something more low level than malloc instead, e.g., for some special performance reasons. In other words, there is separation of concerns: the functionality to perform this "XOR transform" is loosely coupled to the functionality to obtain the storage required for the buffer.

    Quote Originally Posted by heatblazer
    Each call to malloc assigns the a copy ptr to the heap, and I have a function that iterrates in the end to free all. As you`ve said in one of my posts "poor man algorithm" but prevents the leaks now.
    While this solution works, it means that you have global variables. Global variables make it more difficult to reason about your program because you have to consider global state. Your XOR_buffer function becomes tightly coupled with this poor man's "garbage collector", so it becomes less reusable, which is a Bad Thing for a utility library.
    Last edited by laserlight; 01-12-2015 at 08:14 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    I am reworking it. It`s not global heap actually. It`s for the utility.c translation unit. Also, I`ve replaced it with my DList, for unlimited size.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can not get valid value from Char* buffer
    By jeffwang in forum C Programming
    Replies: 6
    Last Post: 01-05-2012, 05:00 PM
  2. Char Buffer filtering
    By TGM76 in forum C Programming
    Replies: 3
    Last Post: 08-03-2010, 11:42 PM
  3. how to know if there is some char in the buffer..
    By transgalactic2 in forum C Programming
    Replies: 30
    Last Post: 01-30-2009, 03:27 PM
  4. Using a *char Buffer
    By Hankyaku in forum C++ Programming
    Replies: 2
    Last Post: 04-13-2003, 01:49 AM
  5. Validating the contents of a char buffer
    By mattz in forum C Programming
    Replies: 3
    Last Post: 12-09-2001, 06:21 PM