Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sscanf missing a string after %[^-]s match

Tags:

c

scanf

I have a simple program using sscanf. The problem I am having is that after matching %[^-]s, sscanf seems to just stop matching.

Here is simple code to see what I mean. The %s match after %[^-]s %s is totally ignored.

NOTE: I need that %[^-]s as I need my program to match both of the possible strings.

NOTE 2: I know the code is totally insecure etc. This is just an example!

#include <stdio.h>

int main(void) {
    int matches;
    int num1, num2, num3, num4;
    char *s1[10];
    char *s2[10];
    char *s3[40];
    char *s4[50];
    char *s5[50];
    char *s6[50];
    char *s7[50];

    char fileTest[] = "29 0 8:4 / / rw,relatime shared:1 - ext4 /dev/sda4 rw,errors=remount-ro";
    // char fileTest[] = "160 48 179:56 /inte /var/oil/gaol/org.something.org/media/internal ro,nosuid,relatime - ext4 /dev/mmccc rw,data=ordered";

    matches = sscanf(fileTest, "%d %d %d:%d %s %s %[^-]s %s",
                     &num1, &num2, &num3, &num4, s1, s2, s3, s4);

    printf("matches: %d\n", matches);
    printf("num1: %d\n", num1);
    printf("num2: %d\n", num2);
    printf("num3: %d\n", num3);
    printf("num4: %d\n", num4);
    printf("s1: %s\n", s1);
    printf("s2: %s\n", s2);
    printf("s3: %s\n", s3);
    printf("s4: %s\n", s4);

    return 0;
}
like image 890
Merc Avatar asked Mar 22 '26 06:03

Merc


2 Answers

Note that the s after the %[…] scan set is a literal s, not part of the scan set. In context, %[^-]s will never match the s, so any following conversion fails. The %[^-] part gobbles anything that isn't a dash - (and s isn't a -, so it gets chomped, along with spaces and everything else), then the s isn't matched (because the conversion stops at a - or end of string), so the scanning fails there and the final %s is never matched.

See the POSIX specification of sscanf(). Read it. Reread it. Re-reread it. Re-re-reread it. Today! And the same tomorrow. You can scale back to twice a day for the rest of the week, then once a day for another week, and once a week for a month, and then once a month for the rest of the year, and at least once a year thereafter. The scanf() family of functions are probably the most difficult standard C functions to use really well.

There are other major problems with your code. In particular, char *s1[10]; should be char s1[10];, and similarly for the other arrays. Or you need to go through major exercises in allocating space for the arrays to point to, etc. And, as you're probably aware, the %s (and %[^-]) conversions do not limit the inputs. Use %9s or %49[^-], etc, for appropriate sizes. See also How to prevent scanf() causing a buffer overflow in C?

like image 165
Jonathan Leffler Avatar answered Mar 23 '26 18:03

Jonathan Leffler


Format specifier %[^-] matches everything until a - is encountered; So after having matched this, the next character in the buffer to check against the format string is a - (if any). But if you let this pattern follow a s, i.e. %[^-]s, then nothing will match any more, because the - never matches the required s in the format string.

like image 41
Stephan Lechner Avatar answered Mar 23 '26 20:03

Stephan Lechner