SIGSEGV on strftime (libc.so.6) 使用 gcc (GCC) 5.3.0

SIGSEGV on strftime (libc.so.6) using gcc (GCC) 5.3.0

我有一个用 c 编写的 http 客户端,在某些部分我得到时间并填写缓冲区,我检查了所有输入值是否有效,但是当函数 运行s 它给出分段时故障,行号 77,行:

strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));

我用调试器测试了输入,没有一个是有问题的

使用此命令编译 运行 后

./COMPILED_FILE_NAME https://whosebug.com/ -d 1:1:1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netdb.h>
#include <sys/types.h>
#define HEADER "-h"
#define TIME_STAMP "-d"
#define PROTOCOL "http://"
#define RFC1123FMT "%a, %d %b %Y %H:%M:%S GMT"
#define DEFAULT_PORT 80
#define BUFFER_SIZE 256
typedef struct sockaddr_in sockaddr_t;
void printError(int flag,char * name);
int  parseUrl(char * url,char** host,int * portt ,char ** path);
int checkString(const char * date);
int parseDate(char* date,int * day,int * hour,int* minute);
void freeData();
int socketConnect(char * host,int port,char * page,char* requestType , char * dateRequest );
 char * host; // the url with out any addititons
char * path; // the path after the url

int main(int argc,char * argv[])
{

    time_t now;
    now = time(NULL);
    char timebuf[BUFFER_SIZE/2];
    int headrFlag=0;
    int timeFlag=0;
    int day=0,hour=0,minute=0;

  //  char * host;//=(char*)malloc(sizeof(char)*128);
  //  char * path;//=(char*)malloc(sizeof(char)*128);

    char requestType[BUFFER_SIZE];
    char dateRequest[BUFFER_SIZE];
    bzero(dateRequest,sizeof(dateRequest));

    strcpy(requestType,"GET");
    int port=DEFAULT_PORT;
    if(argc >1 && argc <=5) // the host at least their
    {
// checking the incoming args
        int i = 1;
        for(;i<argc;i++)
        {
            if(strcmp(argv[i],HEADER)==0)
            {
                if(headrFlag==0)
                {
                headrFlag=1;
                strcpy(requestType,"HEAD");
                 }
                else
                {
                    printError(0,"");
                    break;

                }

            }
            else if(strcmp(argv[i],TIME_STAMP)==0)
            {
                // take the date from the next i , if not there as error
                if(timeFlag==0)
                {
                    timeFlag=1;
                    if(i+1!=argc && parseDate(argv[i+1],&day,&hour,&minute)!=-1) // there is date "thing" after the flag
                    {

                        now=now-(day*24*3600+hour*3600+minute*60); //where day, hour and min are the values
                        //from the input
                        strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now));
                        //timebuf holds the correct format of the time

                        sprintf(dateRequest,"If-Modified-Since: %s\n",timebuf);

                            i++;


                            continue;

                    }
                    else
                    {
                        printError(1,"");

                    }

                }
                else
                {
                        printError(0,"");

                }

                    printError(0,"");
                    break;



            }
            else // the host
            {
                if(parseUrl(argv[i],&host,&port,&path)<0)
                {
                    printError(1,"");
                }

            }


        }

        // connect after every thing is valid
            if(host!=NULL){socketConnect(host,port,path,requestType,dateRequest);}else{printError(0,"");}



    }
    else
    {
        printError(1,"");
    }




    return 0;
}

void printError(int flag,char * name)
{
    // 0 wrong command usage
    //1 wrong input
    //2 system call failure
    if(flag==0)
    {
        printf("Usage: client [-h] [-d <time-interval>] <URL>\n");
    }
    else if(flag==1) // wrong input
    {
        printf("wring input\n");
    }
    else // flag ==2 , sys calls
    {
        perror(name);
    }
    freeData();
            exit(-1);


}
// handles the validation of the url
int  parseUrl(char * url,char** host,int * portt ,char ** path)
{

    char * det=":";
    char * det1="/";
    char * port;
    char * temp;
    char * pathValue;
    int pathSize=0,hostSize=0;
    int addSize=0;
    int portNumber=80;


    char * urlToParse;
    if((temp=strstr(url,PROTOCOL))!=NULL && temp==url) // checking http://
    {

        temp=&temp[strlen(PROTOCOL)];
        urlToParse=temp;
        if(strlen(urlToParse) <=1)
            return -1;
    }
    else
    {
        return -1;
    }
    if((temp=strstr(temp,det))!=NULL) // checking port
    {
        int len1 = strlen(temp)-1; // length from the : to the end
        addSize=len1;
        char * temp1;
        if((temp1=strstr(temp,det1))!=NULL)
        {
           pathSize= strlen(temp1);
           pathValue=temp1;
            int portLength= len1-pathSize;
            port = (char*)malloc(sizeof(char)*portLength+1);
            if(port==NULL)
            {
                printError(2,"malloc");
            }
            port[portLength]='[=11=]';
            strncpy(port,++temp,portLength);
            if(checkString(port)<0)
                return -1;
            portNumber=atoi(port);
            free(port);
                addSize=len1+1;


        }

    }
    else // no port
    {
        temp=urlToParse;



        if((temp=strstr(temp,det1))==NULL) // checking filepath
        {
            return -1;
        }
        else
        {
                     pathValue=temp;
                     pathSize=strlen(temp);
                     addSize=pathSize;

        }

    }
        hostSize=strlen(urlToParse)-addSize;

            *host =(char*)malloc(sizeof(char)*(hostSize+1));
            if(*host==NULL)
            {
                printError(2,"malloc");
            }
            **host=NULL;
           * path =(char*)malloc(sizeof(char)*(pathSize+1));
           if(*path==NULL)
           {
            printError(2,"malloc");

           }
            **path=NULL;

          // *path=pathValue;
           strcpy(*path,pathValue);
            *portt=portNumber;

    strncpy(*host,urlToParse,hostSize);




    return 0;
}

// checks if the number is valid
int checkString(const char * date)
{
    if(date==NULL || strcmp(date,"")==0)
    {
        return -1;
    }
    int len = strlen(date);
    if(strlen(date)>1 && strncmp(&date[0],"-",1)==0  )
    {
        date++;
    }
    while(date && strcmp(date,"")!=0)
    {

        if(isdigit(*(date++))==0)
        {
            return -1;
        }
    }
    return 1;
}

// converts from chars to int
int parseDate(char* date,int * day,int * hour,int* minute)
{

char * det=":";
   // int days,hours,minutes;

    char * dayss =   strtok(date,det);
    char * hourss =   strtok(NULL,det);
    char * moinutss =   strtok(NULL,det);
    if(dayss ==NULL || hourss==NULL||moinutss==NULL)
    {
        return -1;
    }

    if(checkString(dayss)<0 || checkString(hourss)<0 || checkString(moinutss)<0  )
        return -1;
    *day = atoi(dayss);
    *hour=  atoi(hourss);
    *minute=atoi(moinutss);
    return 1;



}
// free what ever memory we used
void freeData()
{
    if(host !=NULL)
    {
        free(host);

    }
    if(path!=NULL)
    {
        free(path);
    }

}
// handles the connection to the server
int socketConnect(char * host,int port,char * page,char* requestType , char * dateRequest )
{
            struct in_addr serverIp;
            struct hostent * hostt =NULL;
           hostt= (struct hostent *)gethostbyname(host);
            if(hostt==NULL)
            {
               freeData();
                herror("");
                printf("\n");
                exit(0);
            }
            struct addr_in** addresses = (struct in_addr **)hostt->h_addr_list;
            int i=0;

            //   char * ss= inet_ntoa(((struct in_addr*)hostt->h_addr)->s_addr);

     // serverIp.s_addr=inet_addr(ss);

     struct sockaddr_in packet;

        packet.sin_family=AF_INET;
        packet.sin_port=htons(port);
        packet.sin_addr.s_addr=((struct in_addr*) hostt->h_addr)->s_addr;

    int socketFd ;
    if((socketFd=socket(PF_INET,SOCK_STREAM,0))<0)
    {
        printError(2,"socket");
    }

    if(connect(socketFd,(struct sockaddr*)&packet,sizeof(packet))<0)
    {
        printError(2,"connect");

    }


    char buffer[BUFFER_SIZE*4];
    char * req = malloc(sizeof(requestType)+sizeof(page)+sizeof(dateRequest)+BUFFER_SIZE);
    if(req==NULL)
    {
        freeData(2,"malloc");
    }

        sprintf(req,"%s http://%s%s HTTP/1.0\r\n%s\n",requestType,host,page,dateRequest);



    printf("HTTP request =\n%s\nLEN = %d\n",req,strlen(req));
    send(socketFd,req,strlen(req),0);

    int sizeOfResponse=0;

    int reading=0 ;
    do
    {

        bzero(buffer,sizeof(buffer));
        reading= read(socketFd,buffer,sizeof(buffer),0);
        if(reading >0)
        {
        printf("%s",buffer);
        sizeOfResponse=sizeOfResponse+strlen(buffer);

        }

    }
    while(reading>0);
    printf("\nTotal received response bytes: %d\n",sizeOfResponse);
    close(socketFd);
    free(req);
        freeData();




}

根本原因:您必须 #include <time.h>

原因是如果没有范围内的声明,编译器会假定 gmtime() returns int。实际上它 returns struct tm *,显然在您的平台上指针比整数宽。

您应该启用所有警告并注意它们。