F.MANNOU
F.MANNOU

Reputation: 23

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;
    }

Upvotes: 1

Views: 744

Answers (1)

laverya
laverya

Reputation: 242

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.

Upvotes: 2

Related Questions