Search code examples
cstringcurlsegmentation-faultstrcat

Segmentation Fault in Array and Pointer in C


I am doing program with array and pointer and got this segmentation fault. Can any one explain why I have been getting this segmentation fault in this code.

My Code :

#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
int main(void)
{
        CURL *curl;
        CURLcode res;
        struct curl_slist *headers = NULL;
        char CPID[50] = "98f5b52a59aa4503999894c10bc33dca" ;
        char Uni_ID[10] = "Demo123" ;
        char *postData;
        curl = curl_easy_init();
        if(curl)
        {
                curl_easy_setopt(curl, CURLOPT_URL, "https://avnetagent.iotconnect.io/api/2.0/agent/sync");
                curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
                //postData = "{\"cpId\":\""+CPID+"\",\"uniqueId\":\""+Uni_ID+"\",\"option\":{\"attribute\":false,\"setting\":false,\"protocol\":false,\"device\":false,\"sdkConfig\":false,\"rule\":false}}";
                postData = "{\"cpId\":\"";
                strcat(postData,CPID);
                strcat(postData,"\",\"uniqueId\":\"");
                strcat(postData,Uni_ID);
                strcat(postData,"\",\"option\":{\"attribute\":false,\"setting\":false,\"protocol\":false,\"device\":false,\"sdkConfig\":false,\"rule\":false}}");

                headers = curl_slist_append(headers, "Accept: application/json");
                 headers = curl_slist_append(headers, "Content-Type: application/json");

                curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData);
                /* Perform the request, res will get the return code */
                res = curl_easy_perform(curl);
                /* Check for errors */
                if(res != CURLE_OK)
                fprintf(stderr, "curl_easy_perform() failed: %s\n",
                curl_easy_strerror(res));

                /* always cleanup */
                curl_easy_cleanup(curl);
        }
        return 0;
}

Solution

  • You are 1) writing to memory that you are not allowed to modify and 2) writing to memory that does not belong to you.

    Here

    postData = "{\"cpId\":\"";
    

    you set the pointer postData to point to a string literal, i.e. a constant string that you are not allowed to modify. However, you do

    strcat(postData,CPID);
    

    which will append the string CPID to the string literal. In other words - it will modify the string literal by overwriting its string termination character and further it will copy parts of CPID into the memory just after the string literal. Both operations are invalid.

    What you need is to make postData point to memory that can be modified.

    Fix 1:

    char *postData;            --->   char postData[8192];
    
    postData = "{\"cpId\":\""; --->   strcpy(postData, "{\"cpId\":\"");
    

    Fix 2:

    char *postData;            --->   char *postData = malloc(8192);
                                      assert(postData != NULL);
    
    postData = "{\"cpId\":\""; --->   strcpy(postData, "{\"cpId\":\"");
    
    return 0;                  --->   free(postData);
                                      return 0;
    

    A downside of both fixes are the fixed memory size (i.e. 8192 chars). Will that always be sufficient memory for the data you want to post?

    If you know the upper limit, you can set a fixed size (like I did).

    If you don't know an upper limit, you have to change your code so that you can increase the allocated memory at run-time, e.g. using realloc (possible only for "Fix 2").

    Notice that using "Fix 1" with a very high amount of memory, e.g. char postData[8192000]; is a problem on most systems as they have a size limit for variables with automatic storage duration.

    So to conclude:

    If you know the upper size limit for the data to post and the limit is reasonable small, you can go with the simple Fix 1.

    Otherwise I'll recommend fix 2.