Eleaz.RS Eleaz.RS - 23 days ago 14
C Question

How can I resolve sscanf issue with email?

Here's my code:

#include <stdio.h>

int main(int argc, char **argv)
{
const char example[]="13902796D ; Josefa Moral Fidalgo ; someone@server.com ; 01/03/2001 ; 0 ; 1 ;";
char DNI[10];
char name[100];
char email[100];
char date[10];
int gender;
int uni;

sscanf(example, "%[^;] ; %[^;] ; %[^;] ; %[^;] ; %d ; %d ; ",
DNI, name, email, date, &gender, &uni);

printf("DNI: %s\n", DNI);
printf("Name: %s\n", name);
printf("Email: %s\n", email);
printf("Date: %s\n", date);
printf("Gender: %d\n", gender);
printf("Uni: %d\n", uni);
return 0;
}


And here's the result:

DNI: 13902796D
Name: Josefa Moral Fidalgo
Email:
Date: 01/03/2001
Gender: 0
Uni: 1


But I expect the result:

DNI: 13902796D
Name: Josefa Moral Fidalgo
Email: someone@server.com
Date: 01/03/2001
Gender: 0
Uni: 1


I'm a newbie with C, but I can't find any answer on Internet, nor here on Stackoverflow, and check some books but can't find the reason why the code

sscanf(example, "%[^;] ; %[^;] ; %[^;] ; %[^;] ; %d ; %d ; ",
DNI, name, email, date, &gender, &uni);


doesn't work. Can anyone help me? I can't use other functions than
sscanf
, that's what my professor wants to use in the code.

Answer

Buffer overflow.

How does code know to not overfill DNI[]? Only the address of DNI was passed to sscanf(). Since OP's code did not provide enough space for the input, DNI[] was overwritten leading to undefined behavior (UB).

sscanf(example, "%[^;] ... ", DNI, ....

Instead, pass the maximum number of characters to read, the width. A 9 will limit scan up to 9 characters. As the array is size 10, there will be enough memory for the 9 characters and the appended null character. Code also needs to make the buffers larger to accommodate user input.

char DNI[10*2];
sscanf(example, "%19[^;] ... ", DNI, ....

But was the entire scan right?
A simple method is to record the offset of the scan with " %n". If the scan reached the "%n", n will have a new value.

int n = -1;
sscanf(example, "%9[^;] ;...  %n", DNI, ..., &n);

Put this together

int main(int argc, char **argv) {
    const char example[]="13902796D ; 1 ;";
    char DNI[10*2];
    int uni;

    int n = -1;
    sscanf(example, "%19[^;] ; %d ; %n", DNI, &uni, &n);
    if (n < 0) {
      puts("Fail");
    } else {
      printf("DNI: %s\n", DNI);
      printf("Uni: %d\n", uni);
    }
    return 0;
}

Code still has issues as DNI[] is likely "13902796D " (note trailing space), but that is another issue for OP to handle.

Comments