Search code examples
cscanfx86-64undefined-behaviori386

C different behavior of sscanf i386 vs x86_64 parsing quoted string


I have found strange behavior of sscanf parsing double quoted string on i386 machine.

My code:

char string[] = "\"1597821828\" \"MODIFY\" \"/fullpath/test2\"";
printf("line : %s", string);
int total;
char store_date[12] = "", store_etat_watch[24] = "", store_path[1024] = "";
printf("stores init:%s,%d , %s,%d , %s,%d \n",
       store_date, strlen(store_date),
       store_etat_watch, strlen(store_etat_watch),
       store_path, strlen(store_path));
total = sscanf(string,"%s %s %s", store_date, store_etat_watch, store_path);
printf("stores brut:%s,%d , %s,%d , %s,%d \n",
       store_date, strlen(store_date),
       store_etat_watch, strlen(store_etat_watch),
       store_path, strlen(store_path));

I compile it on a debian arm64 an execute it (here is my Makefile):

CC = gcc

ERROR_CFLAGS = -Wall -W -pedantic -Wextra -Werror CFLAGS = -static -g -O0 $(ERROR_FLAGS) -D_REENTRANT -DLinux LDFLAGS = $(ERROR_FLAGS)

all: sscanf_test

sscanf_test: sscanf_test.c $(CC) $(CFLAGS) sscanf_test.c -o sscanf_test .PHONY:clean

clean: rm -f sscanf_test

result:

line : "1597821828" "MODIFY" "/fullpath/test2"

stores init:,0 , ,0 , ,0

stores brut:"1597821828",12 , "MODIFY",8 , "/fullpath/test2",17

That's the result I expect. Then I compile it on ubuntu i386 and execute it:

result:

line : "1597821828" "MODIFY" "fullpath/test2"

stores init:,0 , ,0 , ,0

stores brut:"1597821828""MODIFY",20 , "MODIFY",8 ,"/fullpath/test2",17

The first string is not correctly parsed. If the string doesn't begin with double quote: 'no problem'.

char string[]="1597821828 \"MODIFY\" \"/fullpath/test2\"";

result:

line : "1597821828" "MODIFY" "/fullpath/test2"

stores init:,0 , ,0 , ,0

stores brut:1597821828,10 , "MODIFY",8 , "/fullpath/test2",17

I do have to parse string beginning with double quote.

Somebody can help me ?


Solution

  • char store_date[12] is too small to store the the string *1597821828* (Quote character replaced by * for clarity.). Result: undeifned behavior (UB). A string of length 12 needs at least 12+1 char. The +1 is for the null character.

    That it seemed to work on some systems is normal for UB; UB isn't "required to fail", it's "anything can happen". If the memory you stepped on outside store_data[12] happened to not be something the compiler was using for anything needed later in the function, it can happen to work. That's what makes undefined behaviour so nasty: testing can't always reveal it.


    Make the destination array large enough and use widths with "%s".

    // char store_date[12]="";
    // total=sscanf(string,"%s",store_date);
    
    char store_date[12+1]="";
    total=sscanf(string,"%12s",store_date);
    

    Mis-matched specifier with strlen()

    // printf("%d \n",strlen(store_path));
    printf("%zu\n",strlen(store_path));