Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 14 Mar 2019 17:28:14 +0100
From: Markus Wichmann <nullplan@....net>
To: musl@...ts.openwall.com
Subject: Re: segfault on sscanf

On Thu, Mar 14, 2019 at 10:46:17AM +0100, Marian Buschsieweke wrote:
> Hi,
> 
> running pdflatex on Alpine Linux for a specific document resulted in a
> segfault, which I could trace down to a specific call to sscanf. This is a
> minimum example to reproduce that segfault:
> 
> 	#include <stdio.h>
> 	
> 	int main(void) {
> 		const char *too_parse = "0 1 -1 0";
> 		double f1,f2,f3,f4;
> 		char dummy;
> 		sscanf(too_parse, " %lf %lf %lf %lf %c", &f1, &f2, &f3, &f4, &dummy);
> 	
> 		printf("f1=%f, f2=%f, f3=%f, f4=%f, dummy=\"%c\"\n", f1, f2, f3, f4, dummy);
> 	
> 		return 0;
> 	}
> 
> This is the backtrace:
> 
> 	#0  0x00007ffff7fb7eba in vfscanf (f=f@...ry=0x7fffffffe6f8, 
> 	    fmt=<optimized out>, ap=ap@...ry=0x7fffffffe7f8) at src/stdio/vfscanf.c:262
> 	#1  0x00007ffff7fb971a in vsscanf (s=<optimized out>, fmt=<optimized out>, 
> 	    ap=ap@...ry=0x7fffffffe7f8) at src/stdio/vsscanf.c:14
> 	#2  0x00007ffff7fb594d in sscanf (s=<optimized out>, fmt=<optimized out>)
> 	    at src/stdio/sscanf.c:9
> 	#3  0x0000555555555213 in main () at test.c:7
> 
> I have the package Alpine Linux package musl-1.1.21-r0 installed, which is musl
> version 1.1.21 with minimal changes.
> 
> Kind regards,
> Marian

OK, so here's the crashing line:

				while (scanset[(c=shgetc(f))+1])
					s[i++] = c;

It is (unsurprisingly) inside the %c parsing case. At the end of input,
shgetc() returns EOF, which is -1. EOF+1 is therefore 0. And scanset[0]
should be set to 0 (that happens a few lines further up). So the
crashing line should never occur (the line number of the crash is for
the loop body itself).

The error is reproducible whenever sscanf() runs out of input within a
%f conversion, and another conversion happens after it. I would not be
surprised if __floatscan() manages to set the file state wrong on EOF.

The above isn't actually minimal. Here's an even shorter segfault.

  #include <stdio.h>

        int main(void) {
                const char *too_parse = "0";
                double f1;
                char dummy;
                sscanf(too_parse, "%f%c", &f1, &dummy);

                printf("f1=%f, dummy=\"%c\"\n", f1, dummy);

                return 0;
        }

So, I'm off to read __floatscan(). As I recall, it was complicated, so
expect me back in about 10 years or so...

Ciao,
Markus

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.