Search code examples
ccharacterforkexecl

C - Junk characters on output


Let's say, I have two programs - input.c & output.c All I want to do is send some payload/characters in "half pyramid" format into another one using execl() function.

input.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define SIZE 1024

int length;

int main(int argc, char *argv[])
{
    pid_t pid;
    char *target;
    //char payload[length+1];
    char payload[SIZE + 1];
    int status;
    int i = 0;

    if(argc < 2)
    {
        printf("Usage %s <length> <target>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    length = atoi(argv[1]);
    target = argv[2];

    while(i < length)
    {
        pid = fork();

        if(pid != 0)
        {
            waitpid(-1, &status, 0);
            //exit(0);
        }

        if(pid == 0)
        {
            payload[i] = 'A';
            payload[i + 1] = '\0';
            execl(target, target, payload, NULL);
            //printf("%s\n", payload);
        }
        ++i;
    }
    return 0;
}

Commented passages are just for debugging purposes. Because As you can see (while trying), when you want just print it, everything works properly.

output.c (or if you want 'target.c')

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

int main(int argc, char *argv[])
{
    char buffer[30];
    strncpy(buffer, argv[1], sizeof(buffer));
    printf("Output: %s\n", buffer);

    return 0;
}

When I compile input.c like:

gcc input.c -o input

& output.c:

gcc output.c -o output

Ok. Now, everything is prepared. Let's say, I'd like to send a payload - length 6

./input 6 ./output

but all I get on output is just this (or simply with another junks characters):

Output: A
Output: 0A
Output: 0,A
Output: 0,�A
Output: 0,�8A
Output: 0,�8�A

I tried so many things, but all of them failed and output was still the same, as you can see above.

I'd be very grateful if anyone can help me and possibly show me where is problem. Can be problem in using fork() and execl() functions together?


Solution

  • Got it, you should not update payload in the child block code...

    Here's a fix (cannot test it now) :

     while(i < length)
        {
            pid = fork();
            payload[i] = 'A';
            payload[i + 1] = '\0';
    
            if(pid != 0)
            {
                waitpid(-1, &status, 0);
                //exit(0);
            }
    
            if(pid == 0)
            {
                execl(target, target, payload, NULL);
                //printf("%s\n", payload);
            }
            ++i;
        }
    

    [removed unrelated sentence]

    EDIT (additional explanations) : payload updating must be in both parent and child code. If you don't understand why, I can add more explanation.

    EDIT2 (as requested). You want update payload for the next forked child process. In your code, all child code is replaced by execl() into target code. So the fork() is executed only by the first parent process (the root one).

    You have to update payload by the first parent and make it accessible too all the children. Putting it into this block won't work either :

    // block only executed by the first parent.
    if(pid != 0)
    {
        waitpid(-1, &status, 0);
    }
    

    Therefore, You must update it in a place both accessible by the parent and the child : after the fork(), before if(pid == 0) block.

    In your code, you increment i in the common block, but the parent's payload is never updated. So in the child block, just before the execl(), your adding 'A\0' at the end of an uninitialized C string.