The following issue has been SUBMITTED.
======================================================================
http://austingroupbugs.net/view.php?id=110
======================================================================
Reported By: msbrown
Assigned To: ajosey
======================================================================
Project: 1003.1(2008)/Issue 7
Issue ID: 110
Category: System Interfaces
Type: Omission
Severity: Objection
Priority: normal
Status: Under Review
Name: Mark Brown
Organization: IBM
User Reference:
Section: memchr
Page Number: 1284
Line Number: 42163
Final Accepted Text:
======================================================================
Date Submitted: 2009-06-30 19:39 UTC
Last Modified: 2009-06-30 19:39 UTC
======================================================================
Summary: memchr input process order
Description:
_____________________________________________________________________________
OBJECTION Enhancement Request
Number 39
ebb9:xxxxxxx Defect in XSH memchr (rdvk#
1)
{ebb.memchr} Wed, 27 May 2009 13:58:36 +0100
(BST)
_____________________________________________________________________________
Traditional implementations of memchr process the input in ascending
order. This has the advantage that when the object size of s is not
known, but c occurs within the object, the caller can pass a value of
n that is larger than the actual object size without dereferencing
inaccessible memory. However, while the standard (and C99) is
explicit that it is permissible to pass n smaller than the object size
of s, it is silent on whether passing a larger n is well-defined.
In contrast, consider the wording for fprintf when dealing with the
%.*s specifier, from line 29938:
"If the precision is not specified or is greater than the size of the
array, the application shall ensure that the array contains a null
byte."
Many implementations of the *printf family use memchr to implement
this statement; for example,
http://git.sv.gnu.org/cgit/gnulib.git/tree/lib/vasnprintf.c?id=d4ca645#n197
However, if memchr does not have any strict requirement on evaluation
order, then this invokes undefined behavior. For example, here is a
bug report showing what happens when memchr does not have the
traditional behavior, but dereferences memory that fits with the n
argument to memchr but not within the actual array passed to printf:
http://www.alphalinux.org/archives/axp-list/March2001/0337.shtml
Likewise, application writers have noticed that it is possible to
write faster code for finding a NUL byte, if one is present within a
bounded length, by using memchr rather than strnlen, since the former
has fewer conditionals (bounds check and search for NUL) than the
latter (bounds check, search for NUL, and search for c). For example:
http://git.sv.gnu.org/cgit/gnulib.git/tree/lib/strnlen1.c?id=d4ca645
But again, this usage is rendered unsafe unless memchr is specified
to behave like strnlen and not dereference past the match.
Desired Action:
At the end of the paragraph at line 42164, append a sentence with CX
shading:
If n is larger than the object pointed to by s, the application shall
ensure that an instance of c occurs within the object.
Change the rationale at line 42174 from:
None.
to:
Although C99 is silent on the behavior of memchr when s points to an
array smaller than n bytes, this specification requires memchr to
behave as if it accesses bytes in ascending order, thus making
memchr(s,0,n) safe to use as a faster alternative to strnlen(s,n) when
determining if the end of a null-terminated string occurs within n
bytes.
According to ebb9:xxxxxxx on 5/27/2009 6:58 AM:
> Likewise, application writers have noticed that it is possible to
> write faster code for finding a NUL byte, if one is present within a
> bounded length, by using memchr rather than strnlen, since the former
> has fewer conditionals (bounds check and search for NUL) than the
> latter (bounds check, search for NUL, and search for c).
Correction - I meant to compare memchr(s,c,n) to strchr(s,c) where c is
known to occur in s; strchr requires a search for c and for NUL, and the
search for two bytes in parallel is typically more expensive than a
bounds
check and single search. There is no strnchr, so nothing is
standardized
that performs all three of bounds check, search for NUL, and search for
c
at once. (That behavior is also useful--for example, gnulib provides a
function memchr2--but it can wait for another day to be standardized).
But one point remains - many applications use memchr(s,0,n) rather than
strnlen(s,n) because strnlen was not present in earlier standards. So
this aardvark is still useful in standardizing this relationship.
> Change the rationale at line 42174 from:
>
> None.
>
> to:
>
> Although C99 is silent on the behavior of memchr when s points to an
> array smaller than n bytes, this specification requires memchr to
> behave as if it accesses bytes in ascending order, thus making
> memchr(s,0,n) safe to use as a faster alternative to strnlen(s,n) when
> determining if the end of a null-terminated string occurs within n
> bytes.
Therefore, we may want to strike the word 'faster' in this proposed
rationale.
======================================================================
|