Bug 219926

Summary: sscanf(3): Inconsistent return value on match failures with patterns like "%*s%u" when compared to other implementations
Product: Base System Reporter: Tobias Kortkamp <tobik>
Component: standardsAssignee: freebsd-standards (Nobody) <standards>
Status: New ---    
Severity: Affects Only Me CC: cem
Priority: ---    
Version: CURRENT   
Hardware: Any   
OS: Any   

Description Tobias Kortkamp freebsd_committer freebsd_triage 2017-06-11 14:13:55 UTC
When using a pattern that starts with "%*s" followed by one or more
other conversions, the sscanf(3) implementation in FreeBSD's libc
behaves differently than the sscanf() implementations in other libcs.
For example running this small test program on a bunch of different
systems gives the following results:

#include <stdio.h>

int
main(int argc, char *argv[])
{
	unsigned int i;
	int n = sscanf("foo", "%*s%u", &i);
	printf("n = %d\n", n);
	return 0;
}

n = 0 on FreeBSD 11.0 and 12.0-CURRENT
n = 0 on DragonFly BSD 4.6.0rc2
n = 0 on NetBSD 7.0.1
n = -1 on Ubuntu 16.04 (Glibc 2.23)
n = -1 on Alpine Linux (musl 1.1.16)
n = -1 on OpenBSD 6.1

Glibc, musl, and OpenBSD's libc all return EOF in this case.

netpbm's ppmtoarbtxt uses a similar pattern and would fail to work
correctly on FreeBSD because it expects that EOF is returned after a
match failure.  This has been worked around now upstream by not using
"%*s" first in the pattern.  But I'm wondering if this a bug or if
this is ok?
Comment 1 Conrad Meyer freebsd_committer freebsd_triage 2017-06-11 16:11:42 UTC
The C11 standard says:

-------------------------------8<-------------------------------
Returns
3 The sscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the sscanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
-------------------------------8<-------------------------------

So the question is — is "%*s" a conversion?

From the fscanf part of C11:

-------------------------------8<-------------------------------
Each conversion specification is introduced by the character %.
After the %, the following appear in sequence:
— An optional assignment-suppressing character *.
— An optional decimal integer greater than zero that specifies the maximum field width (in characters).
— An optional length modifier that specifies the size of the receiving object.
— A conversion specifier character that specifies the type of conversion to be applied.
-------------------------------8<-------------------------------

So... maybe?