View Issue Details

IDProjectCategoryView StatusLast Update
00011731003.1(2016/18)/Issue7+TC2System Interfacespublic2024-06-11 09:09
Reportereblake Assigned To 
PrioritynormalSeverityObjectionTypeError
Status ClosedResolutionAccepted As Marked 
NameEric Blake
OrganizationRed Hat
User Referencescanf
Sectionscanf
Page Number950
Line Number32272
Interp Status---
Final Accepted Text0001173:0004241
Summary0001173: scanf("%mc") contradiction
DescriptionThe standard is clear that the conversion specifications for %s and %[ require the caller to supply an argument large enough for storing a terminating NUL, even though the terminating NUL is not part of the count of input bytes consumed if %n is used. Similarly, %ms and %m[ allocate enough memory to include a terminating NUL.

However, the standard has contradictory information on a terminating NUL when %c is in force. Line 32274 says %mc "shall cause a memory buffer to be allocated to hold the string converted including a terminating null character"; while line 32377 says "No null byte is added" without regards to whether m was in use.

The addition of the 'm' modifier in POSIX was modeled after the historical glibc behavior of "%as" (glibc has since followed POSIX' lead and now treats %a as parsing floating point, and prefers using %ms instead of %as for allocating a string). But glibc has NEVER written a trailing NUL byte for %mc (and never supported the older %ac, only %as). As such, this has the following consequences:
char *ptr = NULL;
int count;
if (scanf("%1ms%n", &ptr, &count) == 1 && count == 1)
  assert(ptr[1] == 0); // safe
}
free (ptr);
if (scanf("%mc%n", &ptr, &count) == 1 && count == 1)
  ptr[1]; // undefined behavior; might be beyond the end of the malloc'd space, and even if in range, it does not have a defined value
}

The standard should be clear that the allocated buffer for 'm' does NOT have to include a trailing NUL byte for %c conversion, and that portable applications must not assume anything about the memory beyond the maximum field size or smaller %n count of input consumed in that situation. Alternatively, the standard could require that %mc allocates room for and writes a trailing NUL byte, although glibc would then need to be patched to be compliant.
Desired ActionAt line 32272 (XSI scanf() DESCRIPTION), change the CX shaded text:

which shall cause a memory buffer to be allocated to hold the string converted
including a terminating null character.
to
which shall cause a memory buffer to be allocated to hold the conversion results. If the specifier is %s or %[, the allocated buffer shall include space for a terminating null character.
Tagstc3-2008

Relationships

related to 0001375 Closed *scanf() 'm' allocation char v. wchar_t problems 

Activities

geoffclare

2019-02-07 11:42

manager   bugnote:0004241

Proposed changes (including a fix for referring incorrectly to %s etc. as conversion specifiers):

On page 950 line 32272 section fscanf(), change:
The <tt>%c</tt>, <tt>%s</tt>, and <tt>%[</tt> conversion specifiers shall accept an optional assignment-allocation character 'm', which shall cause a memory buffer to be allocated to hold the string converted including a terminating null character.
to:
The <tt>c</tt>, <tt>s</tt>, and <tt>[</tt> conversion specifiers shall accept an optional assignment-allocation character 'm', which shall cause a memory buffer to be allocated to hold the conversion results. If the conversion specifier is <tt>s</tt> or <tt>[</tt>, the allocated buffer shall include space for a terminating null character.

On page 1004 line 34177 section fwscanf(), change:
The <tt>%c</tt>, <tt>%s</tt>, and <tt>%[</tt> conversion specifiers shall accept an optional assignment-allocation character 'm', which shall cause a memory buffer to be allocated to hold the wide-character string converted including a terminating null wide character.
to:
The <tt>c</tt>, <tt>s</tt>, and <tt>[</tt> conversion specifiers shall accept an optional assignment-allocation character 'm', which shall cause a memory buffer to be allocated to hold the conversion results. If the conversion specifier is <tt>s</tt> or <tt>[</tt>, the allocated buffer shall include space for a terminating null wide character.

Issue History

Date Modified Username Field Change
2017-11-29 18:24 eblake New Issue
2017-11-29 18:24 eblake Name => Eric Blake
2017-11-29 18:24 eblake Organization => Red Hat
2017-11-29 18:24 eblake User Reference => scanf
2017-11-29 18:24 eblake Section => scanf
2017-11-29 18:24 eblake Page Number => 950
2017-11-29 18:24 eblake Line Number => 32272
2017-11-29 18:24 eblake Interp Status => ---
2019-02-07 11:42 geoffclare Note Added: 0004241
2019-02-14 16:51 geoffclare Final Accepted Text => 0001173:0004241
2019-02-14 16:51 geoffclare Status New => Resolved
2019-02-14 16:51 geoffclare Resolution Open => Accepted As Marked
2019-02-14 16:52 geoffclare Tag Attached: tc3-2008
2019-11-08 10:48 geoffclare Status Resolved => Applied
2020-07-15 14:09 geoffclare Relationship added related to 0001375
2024-06-11 09:09 agadmin Status Applied => Closed