简体   繁体   中英

Segmentation fault in a long string

I am writing a function which prints out to as standard output, like how a regular printf function does but instade of taking indicators like %d or %s it takes {i} or {s}. The problem i have is that when the string of the format argument is too long about 23 characters, i get a segmentation fault at the line where i am calling vfprintf function.

        int mr_asprintf(const char *format, ...)
        {
            int i;
            char *newFormat = calloc(1,sizeof(char));
            char integer[3] = "%d";
            char str[3] = "%s";
            char tmpStr[2];
            va_list args;
            newFormat[0] ='\0';
            tmpStr[1] = '\0';
            for(i=0;format[i]!='\0';i++) // convert to printf syntaxe
            {
                if(format[i]=='{' && format[i+2]=='}') //check if it's {x}
                {
                    switch(format[i+1]) 
                    {
                        case 'i':
                            strcat(newFormat,integer);
                            i += 2;
                            break;
                        case 's':
                            strcat(newFormat,str);
                            i += 2;
                            break;
                    }
                }
                else
                {
                    tmpStr[0] = format[i];
                    strcat(newFormat,tmpStr);
                }

            }
            va_start(args,format);
            int s = vfprintf(stdout,newFormat,args);
            va_end(args);
            free(newFormat);
            return s;
        }

Test example :

    int main()
    {

        char *result = mr_asprintf("bce }edadacba{i}}aa}da{s}fe aeaee d{i}cefaa",55,"XXX",66);
        printf("%s\n",result);
        return 0;
    }

Your string newFormat is being allocated as size 1, and you are appending to it with strcat - but strcat does not do any array resizing, so newFormat will soon begin to stomp on unallocated memory. The length of your output string will always be <= the length of the input string, so you should probably allocate a string of that size.

Finally, while this shouldn't cause a segfault in vprintf, it might cause unexpected behavior later -

for(i=0;format[i]!='\0';i++) // convert to printf syntaxe
{
    if(format[i]=='{' && format[i+2]=='}') //check if it's {x}

You check if the current location is the end of the string, and then check two characters after the current location for a closing bracket, without checking if the string ended on the next space . This could lead to reads outside of the allocated memory for your array. Replacing the if statement with if(format[i]=='{' && (format[i+1]=='i' || format[i+1]=='s') && format[i+2]=='}') would avoid the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM