Search code examples
clinuxsocketsclient

Why "bad file descriptor" appears only in Linux?


why does the sendto function return error: Bad File descriptor? This only happens on Linux (in Windows it works properly). Here is my code: json object hb is a classical json object, such as { "name": "alfa", "surname": "beta"}, converted to string by its method

int fd;
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
    print_time();
    perror("Socket failed\n");
    exit(EXIT_FAILURE);
}

struct sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
//memset(&cliaddr, 0, sizeof(cliaddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9900);
serveraddr.sin_addr.s_addr = inet_addr("192.168.1.96");
char ui_request_str[] = "";

strcpy(ui_request_str, json_object_to_json_string(hb));

  if (sendto(fd, ui_request_str, strlen(ui_request_str), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("Error");
    }
    else
    {
        debug_level > 0 && printf("message sent: %s\n", ui_request_str);
    }

    close(fd);

Solution

  • problem

    Your problem comes from memory that you don't allocate:

    char ui_request_str[] = "";
    strcpy(ui_request_str, json_object_to_json_string(hb));
    

    Of first line, you allocate a one bytes array. On second line, you try to write the memory you reserved with the output of json_object_to_json_string

    You are code generates a buffer overruns:

    From man strcpy:

    Bugs
    If the destination string of a strcpy() is not large enough, then anything might happen. Overflowing fixed-length string buffers is a favorite cracker technique for taking complete control of the machine. Any time a program reads or copies data into a buffer, the program first needs to check that there's enough space. This may be unnecessary if you can show that overflow is impossible, but be careful: programs can get changed over time, in ways that may make the impossible possible.

    solution

    Don't make ui_request_str an array, make it a pointer:

    char * ui_request_str[];
    ui_request_str = json_object_to_json_string(hb);
    
    if (NULL == ui_request_str) {
        perror(";json_object_to_json_string");
        exit(0);
    }
    
    if (sendto(fd, ui_request_str, strlen(ui_request_str), 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
    {
        perror("Error");
    }
    else
    {
        debug_level > 0 && printf("message sent: %s\n", ui_request_str);
    }